﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Text;
using Towel;
using static Towel.Statics;

namespace Towel_Generating
{
	internal static class Omnitree
	{
		internal static void Generate(
			int dimensions = 10)
		{
			StringBuilder file = new StringBuilder();
			file.AppendLine($@"//------------------------------------------------------------------------------");
			file.AppendLine(@"// <auto-generated>");
			file.AppendLine($@"//	This code was generated from ""{sourcefilepath()}"".");
			file.AppendLine(@"// </auto-generated>");
			file.AppendLine($@"//------------------------------------------------------------------------------");
			file.AppendLine($@"");
			file.AppendLine($@"using System;");
			file.AppendLine($@"using System.Numerics;");
			file.AppendLine($@"using static Towel.Syntax;");
			file.AppendLine($@"using static Towel.DataStructures.Omnitree;");
			file.AppendLine($@"namespace Towel_Generating.DataStructures");
			file.AppendLine($@"{{");
			file.AppendLine($@"	#region Notes");
			file.AppendLine($@"");
			file.AppendLine($@"	// Visualizations--------------------------------------------------");
			file.AppendLine($@"	//");
			file.AppendLine($@"	// 1 Dimensional:");
			file.AppendLine($@"	//");
			file.AppendLine($@"	//  -1D |-----------|-----------| +1D");
			file.AppendLine($@"	//");
			file.AppendLine($@"	//       <--- 0 ---> <--- 1 --->");
			file.AppendLine($@"	//");
			file.AppendLine($@"	// 2 Dimensional:");
			file.AppendLine($@"	//       _____________________");
			file.AppendLine($@"	//      |          |          |  +2D");
			file.AppendLine($@"	//      |          |          |   ^");
			file.AppendLine($@"	//      |     2    |     3    |   |");
			file.AppendLine($@"	//      |          |          |   |");
			file.AppendLine($@"	//      |----------|----------|   |");
			file.AppendLine($@"	//      |          |          |   |");
			file.AppendLine($@"	//      |          |          |   |");
			file.AppendLine($@"	//      |     0    |     1    |   |");
			file.AppendLine($@"	//      |          |          |   v");
			file.AppendLine($@"	//      |__________|__________|  -2D");
			file.AppendLine($@"	//");
			file.AppendLine($@"	//       -1D <-----------> +1D ");
			file.AppendLine($@"	//");
			file.AppendLine($@"	// 3 Dimensional:");
			file.AppendLine($@"	//");
			file.AppendLine($@"	//            +3D     _____________________");
			file.AppendLine($@"	//           7       /         /          /|");
			file.AppendLine($@"	//          /       /    6    /     7    / |");
			file.AppendLine($@"	//         /       /---------/----------/  |");
			file.AppendLine($@"	//        /       /    2    /     3    /|  |");
			file.AppendLine($@"	//       L       /_________/__________/ |  |");
			file.AppendLine($@"	//    -3D       |          |          | | /|          +2D");
			file.AppendLine($@"	//              |          |          | |/ |           ^");
			file.AppendLine($@"	//              |     2    |     3    | /  |           |");
			file.AppendLine($@"	//              |          |          |/|  | <-- 5     |");
			file.AppendLine($@"	//              |----------|----------| |  |           |");
			file.AppendLine($@"	//              |          |          | |  /           |");
			file.AppendLine($@"	//              |          |          | | /            |");
			file.AppendLine($@"	//              |     0    |     1    | |/             |");
			file.AppendLine($@"	//              |          |          | /              v");
			file.AppendLine($@"	//              |__________|__________|/              -2D");
			file.AppendLine($@"	//             ");
			file.AppendLine($@"	//                   ^");
			file.AppendLine($@"	//                   |");
			file.AppendLine($@"	//                   4 (behind 0)");
			file.AppendLine($@"	//");
			file.AppendLine($@"	//               -1D <-----------> +1D");
			file.AppendLine($@"");
			file.AppendLine($@"	#endregion Notes");
			file.AppendLine($@"");

			for (int i = 1; i <= dimensions; i++)
			{
				void AppendLines(Func<int, string> func)
				{
					for (int j = 1; j <= i; j++)
					{
						file.AppendLine();
					}
				}

				#region Partials

				Dictionary<string, string> ___ = new Dictionary<string, string>();

				IEnumerable<int> ie = Enumerable.Range(1, i);

				#region A1...

				___["A1..."] = string.Join(", ", ie.Select(n => $"A{n}"));

				#endregion

				#region Hidden

				#region A1 axis1...

				___["A1 axis1..."] = string.Join(", ", ie.Select(n => $"A{n} axis{n}"));

				#endregion

				#region default(A1)...

				___["default(A1)..."] = string.Join(", ", ie.Select(n => $"default(A{n})"));

				#endregion

				#region this.Axis1 = axis1;...

				___["this.Axis1 = axis1;..."] = string.Join(@"
				", ie.Select(n => $"this.Axis{n} = axis{n};"));

				#endregion

				#region /// <typeparam name=""A1"">The generic type of the 1 dimension.</typeparam>...

				___[@"/// <typeparam name=""A1"">The generic type of the 1 dimension.</typeparam>..."] =
					string.Join(@"
			", ie.Select(n => $@"/// <typeparam name=""A{n}"">The generic type of the {n} dimension.</typeparam>..."));

				#endregion

				#region /// <param name=""axis1"">The location along axis 1.</param>...

				___[@"/// <param name=""axis1"">The location along axis 1.</param>..."] =
					string.Join(@"
			", ie.Select(n => $@"/// <param name=""axis{n}"">The location along axis {n}.</param>"));

				#endregion

				// /// <summary>The value along axis 1.</summary>
				// public A1 Axis1;...
				#region

				___[$@"/// <summary>The value along axis 1.</summary>
			public A1 Axis1;..."] =
					string.Join(@"
				", ie.Select(n => $@"/// <summary>The value along axis {n}.</summary>
			public A{n} Axis{n};"));

				#endregion

				#region this.Axis1 = axis1;...

				___[$@"this.Axis1 = axis1;..."] =
					string.Join(@"
				", ie.Select(n => $@"this.Axis{n} = axis{n};"));

				#endregion

				// /// <summary>The minimum value along the 1 dimension.</summary>
				// public Bound<A1> Min1;
				// /// <summary>The maximum value along the 1 dimension.</summary>
				// public Bound<A1> Max1;...
				#region

				___[
$@"/// <summary>The minimum value along the 1 dimension.</summary>
			public Bound<A1> Min1;
			/// <summary>The maximum value along the 1 dimension.</summary>
			public Bound<A1> Max1;..."] =
					string.Join($@"

			", ie.Select(n =>
			$@"/// <summary>The minimum value along the {n} dimension.</summary>
			public Bound<A{n}> Min{n};
			/// <summary>The maximum value along the {n} dimension.</summary>
			public Bound<A{n}> Max{n};"));

				#endregion

				#region Bound<A1>.None, Bound<A1>.None...

				___["Bound<A1>.None, Bound<A1>.None..."] = string.Join(@",
				", ie.Select(n => $"Bound<A{n}>.None, Bound<A{n}>.None"));

				#endregion

				#region Bound<A1> min1, Bound<A1> max1...

				___["Bound<A1> min1, Bound<A1> max1..."] = string.Join(@",
				", ie.Select(n => $"Bound<A{n}> min{n}, Bound<A{n}> max{n}"));

				#endregion

				#region out A1 min1, out A1 max1...

				___["out A1 min1, out A1 max1..."] = string.Join(@",
			", ie.Select(n => $"out A{n} min{n}, out A{n} max{n}"));

				#endregion

				// this.Min{j} = min{j};
				// this.Max{ j} = max{ j};
				#region

				___[
				@"this.Min1 = min1;
				this.Max1 = max1;..."] =
					string.Join($@"

			", ie.Select(n =>
			$@"this.Min{n} = min{n};
			this.Max{n} = max{n};"));

				#endregion

				#region /// <typeparam name=""A1"">The generic type of the 1 dimension.</typeparam>...

				___[@"/// <typeparam name=""A1"">The generic type of the 1 dimension.</typeparam>..."] =
					string.Join(@"
		", ie.Select(n => $@"/// <typeparam name=""A{n}"">The generic type of the {n} dimension.</typeparam>"));

				#endregion

				#region /// <param name=""axis1"">The location of the item along the 1 dimension.</param>...

				___[@"/// <param name=""axis1"">The location of the item along the 1 dimension.</param>..."] =
					string.Join(@"
		", ie.Select(n => $@"/// <param name=""axis{n}"">The location of the item along the {n} dimension.</param>"));

				#endregion

				#region out A1 axis1...

				___["out A1 axis1..."] = string.Join(@", ", ie.Select(n => $@"out A{n} axis{n}"));

				#endregion

				#region /// <param name=""min1"">The minimum bound of the item along the 1 dimension.</param>

				___[@"/// <param name=""min1"">The minimum bound of the item along the 1 dimension.</param>..."] =
					string.Join(@"
		", ie.Select(n => $@"/// <param name=""min{n}"">The minimum bound of the item along the {n} dimension.</param>"));

				#endregion

				#region /// <param name=""max<#= j #>"">The maximum bound of the item along the <#= j #> dimension.</param>

				___[@"/// <param name=""max1"">The maximum bound of the item along the 1 dimension.</param>..."] =
					string.Join(@"
		", ie.Select(n => $@"/// <param name=""max{n}"">The maximum bound of the item along the {n} dimension.</param>"));

				#endregion

				#region out Bound<A1> min1, out Bound<A1> max1...

				___["out Bound<A1> min1, out Bound<A1> max1..."] = string.Join(@", ", ie.Select(n => $@"out Bound<A{n}> min{n}, out Bound<A{n}> max{n}"));

				#endregion

				#region out A1 min1a, out A1 max1a...

				___["out A1 min1a, out A1 max1a..."] = string.Join(@",
						", ie.Select(n => $"out A{n} min{n}a, out A{n} max{n}a"));

				#endregion

				#region A1 min1; A1 max1;...

				___["A1 min1; A1 max1;..."] = string.Join(@"
					", ie.Select(n => $@"A{n} min{n}; A{n} max{n};"));

				#endregion

				#region minBound1 = min1; maxBound1 = max1;...

				___["min1 = min1a; max1 = max1a;..."] = string.Join(@"
					", ie.Select(n => $@"min{n} = min{n}a; max{n} = max{n}a;"));

				#endregion

				//string __(string key) => partials[key];

				#endregion

				#endregion

				file.AppendLine($@"		#region {i} Dimensional");
				file.AppendLine($@"");
				file.AppendLine($@"		/// <summary>Represents a {i}D vector.</summary>");
				AppendLines(n => $@"		/// <typeparam name=""A{n}"">The generic type of the {n} dimension.</typeparam>...");
				file.AppendLine($@"		public struct Vector<{Join(1..(i + 1), n => $"A{n}", ", ")}>");
				file.AppendLine($@"		{{");


				file.AppendLine($@"		}}");
			}


//			for (int i = 1; i <= dimensions; i++)
//			{
//				#region partials

//				IEnumerable<int> ie = Enumerable.Range(1, i);

//				#region A1...

//				partials["A1..."] = string.Join(", ", ie.Select(n => $"A{n}"));

//				#endregion

//				#region A1 axis1...

//				partials["A1 axis1..."] = string.Join(", ", ie.Select(n => $"A{n} axis{n}"));

//				#endregion

//				#region default(A1)...

//				partials["default(A1)..."] = string.Join(", ", ie.Select(n => $"default(A{n})"));

//				#endregion

//				#region this.Axis1 = axis1;...

//				partials["this.Axis1 = axis1;..."] = string.Join(@"
//				", ie.Select(n => $"this.Axis{n} = axis{n};"));

//				#endregion

//				#region /// <typeparam name=""A1"">The generic type of the 1 dimension.</typeparam>...

//				partials[@"/// <typeparam name=""A1"">The generic type of the 1 dimension.</typeparam>..."] =
//					string.Join(@"
//			", ie.Select(n => $@"/// <typeparam name=""A{n}"">The generic type of the {n} dimension.</typeparam>..."));

//				#endregion

//				#region /// <param name=""axis1"">The location along axis 1.</param>...

//				partials[@"/// <param name=""axis1"">The location along axis 1.</param>..."] =
//					string.Join(@"
//			", ie.Select(n => $@"/// <param name=""axis{n}"">The location along axis {n}.</param>"));

//				#endregion

//				// /// <summary>The value along axis 1.</summary>
//				// public A1 Axis1;...
//				#region

//				partials[$@"/// <summary>The value along axis 1.</summary>
//			public A1 Axis1;..."] =
//					string.Join(@"
//				", ie.Select(n => $@"/// <summary>The value along axis {n}.</summary>
//			public A{n} Axis{n};"));

//				#endregion

//				#region this.Axis1 = axis1;...

//				partials[$@"this.Axis1 = axis1;..."] =
//					string.Join(@"
//				", ie.Select(n => $@"this.Axis{n} = axis{n};"));

//				#endregion

//				// /// <summary>The minimum value along the 1 dimension.</summary>
//				// public Bound<A1> Min1;
//				// /// <summary>The maximum value along the 1 dimension.</summary>
//				// public Bound<A1> Max1;...
//				#region

//				partials[
//$@"/// <summary>The minimum value along the 1 dimension.</summary>
//			public Bound<A1> Min1;
//			/// <summary>The maximum value along the 1 dimension.</summary>
//			public Bound<A1> Max1;..."] =
//					string.Join($@"

//			", ie.Select(n =>
//			$@"/// <summary>The minimum value along the {n} dimension.</summary>
//			public Bound<A{n}> Min{n};
//			/// <summary>The maximum value along the {n} dimension.</summary>
//			public Bound<A{n}> Max{n};"));

//				#endregion

//				#region Bound<A1>.None, Bound<A1>.None...

//				partials["Bound<A1>.None, Bound<A1>.None..."] = string.Join(@",
//				", ie.Select(n => $"Bound<A{n}>.None, Bound<A{n}>.None"));

//				#endregion

//				#region Bound<A1> min1, Bound<A1> max1...

//				partials["Bound<A1> min1, Bound<A1> max1..."] = string.Join(@",
//				", ie.Select(n => $"Bound<A{n}> min{n}, Bound<A{n}> max{n}"));

//				#endregion

//				#region out A1 min1, out A1 max1...

//				partials["out A1 min1, out A1 max1..."] = string.Join(@",
//			", ie.Select(n => $"out A{n} min{n}, out A{n} max{n}"));

//				#endregion

//				// this.Min{j} = min{j};
//				// this.Max{ j} = max{ j};
//				#region

//				partials[
//				@"this.Min1 = min1;
//				this.Max1 = max1;..."] =
//					string.Join($@"

//			", ie.Select(n =>
//			$@"this.Min{n} = min{n};
//			this.Max{n} = max{n};"));

//				#endregion

//				#region /// <typeparam name=""A1"">The generic type of the 1 dimension.</typeparam>...

//				partials[@"/// <typeparam name=""A1"">The generic type of the 1 dimension.</typeparam>..."] =
//					string.Join(@"
//		", ie.Select(n => $@"/// <typeparam name=""A{n}"">The generic type of the {n} dimension.</typeparam>"));

//				#endregion

//				#region /// <param name=""axis1"">The location of the item along the 1 dimension.</param>...

//				partials[@"/// <param name=""axis1"">The location of the item along the 1 dimension.</param>..."] =
//					string.Join(@"
//		", ie.Select(n => $@"/// <param name=""axis{n}"">The location of the item along the {n} dimension.</param>"));

//				#endregion

//				#region out A1 axis1...

//				partials["out A1 axis1..."] = string.Join(@", ", ie.Select(n => $@"out A{n} axis{n}"));

//				#endregion

//				#region /// <param name=""min1"">The minimum bound of the item along the 1 dimension.</param>

//				partials[@"/// <param name=""min1"">The minimum bound of the item along the 1 dimension.</param>..."] =
//					string.Join(@"
//		", ie.Select(n => $@"/// <param name=""min{n}"">The minimum bound of the item along the {n} dimension.</param>"));

//				#endregion

//				#region /// <param name=""max<#= j #>"">The maximum bound of the item along the <#= j #> dimension.</param>

//				partials[@"/// <param name=""max1"">The maximum bound of the item along the 1 dimension.</param>..."] =
//					string.Join(@"
//		", ie.Select(n => $@"/// <param name=""max{n}"">The maximum bound of the item along the {n} dimension.</param>"));

//				#endregion

//				#region out Bound<A1> min1, out Bound<A1> max1...

//				partials["out Bound<A1> min1, out Bound<A1> max1..."] = string.Join(@", ", ie.Select(n => $@"out Bound<A{n}> min{n}, out Bound<A{n}> max{n}"));

//				#endregion

//				#region out A1 min1a, out A1 max1a...

//				partials["out A1 min1a, out A1 max1a..."] = string.Join(@",
//						", ie.Select(n => $"out A{n} min{n}a, out A{n} max{n}a"));

//				#endregion

//				#region A1 min1; A1 max1;...

//				partials["A1 min1; A1 max1;..."] = string.Join(@"
//					", ie.Select(n => $@"A{n} min{n}; A{n} max{n};"));

//				#endregion

//				#region minBound1 = min1; maxBound1 = max1;...

//				partials["min1 = min1a; max1 = max1a;..."] = string.Join(@"
//					", ie.Select(n => $@"min{n} = min{n}a; max{n} = max{n}a;"));

//				#endregion

//				string __(string key) => partials[key];

//				#endregion


//				file.AppendLine(
//$@"		#region {i} Dimensional

//		/// <summary>Represents a {i}D vector.</summary>
//		{__(@"/// <typeparam name=""A1"">The generic type of the 1 dimension.</typeparam>...")}
//		public struct Vector<{__("A1...")}>
//		{{
//			{__(@"/// <summary>The value along axis 1.</summary>
//			public A1 Axis1;...")}

//			/// <summary>Returns a vector with defaulted values.</summary>
//			public static Vector<{__("A1...")}> Default =>
//				new Vector<{__("A1...")}>({__("default(A1)...")});

//			/// <summary>A location along each axis.</summary>
//			{__(@"/// <param name=""axis1"">The location along axis 1.</param>...")}
//			public Vector({__("A1 axis1...")})
//			{{
//				{__("this.Axis1 = axis1;...")}
//			}}
//		}}

//		/// <summary>Represents a {i}D bounding box.</summary>
//		{__(@"/// <typeparam name=""A1"">The generic type of the 1 dimension.</typeparam>...")}
//		public struct Bounds<{__("A1...")}>
//		{{
//			{__($@"/// <summary>The minimum value along the 1 dimension.</summary>
//			public Bound<A1> Min1;
//			/// <summary>The maximum value along the 1 dimension.</summary>
//			public Bound<A1> Max1;...")}

//			/// <summary>Extends infinitely along each axis.</summary>
//			public static Bounds<{__("A1...")}> None =>
//				new Bounds<{__("A1...")}>(
//					{__("Bound<A1>.None, Bound<A1>.None...")});

//			/// <summary>A set of values denoting a range (or lack of range) along each axis.</summary>
// 			public Bounds(
//				{__("Bound<A1> min1, Bound<A1> max1...")})
//			{{
//				{__(@"this.Min1 = min1;
//				this.Max1 = max1;...")}
//			}}
//		}}

//		/// <summary>Delegate for locating an item in {i}D space.</summary>
//		/// <typeparam name=""T"">The generic type of the item to locate.</typeparam>
//		{__(@"/// <typeparam name=""A1"">The generic type of the 1 dimension.</typeparam>...")}
//		/// <param name=""item"">The item to locate.</param>
//		{__(@"/// <param name=""axis1"">The location of the item along the 1 dimension.</param>...")}
//		public delegate void Location<T, {__("A1...")}>(T item, {__("out A1 axis1...")});

//		/// <summary>Delegate for getting the {i}D bounding box of an item.</summary>
//		/// <typeparam name=""T"">The generic type of the item to get the bounding box of.</typeparam>
//		{__(@"/// <typeparam name=""A1"">The generic type of the 1 dimension.</typeparam>...")}
//		/// <param name=""item"">The item to get the bounding box of.</param>
//		{__(@"/// <param name=""min1"">The minimum bound of the item along the 1 dimension.</param>...")}
//		{__(@"/// <param name=""max1"">The maximum bound of the item along the 1 dimension.</param>...")}
//		public delegate void GetBounds<T, {__("A1...")}> (T item, {__("out Bound<A1> min1, out Bound<A1> max1...")});

//		/// <summary>Delegate for getting the {i}D bounding box of an item.</summary>
//		/// <typeparam name=""T"">The generic type of the item to get the bounding box of.</typeparam>
//		{__(@"/// <typeparam name=""A1"">The generic type of the 1 dimension.</typeparam>...")}
//		/// <param name=""item"">The item to get the bounding box of.</param>
//		{__(@"/// <param name=""min1"">The minimum bound of the item along the 1 dimension.</param>...")}
//		{__(@"/// <param name=""max1"">The maximum bound of the item along the 1 dimension.</param>...")}
//		public delegate void GetBoundings<T, {__("A1...")}>(
//			T item,
//			{__("out A1 min1, out A1 max1...")});
		
//		/// <summary>Converts an Omnitree.GetBoundings delegate into an Omnitree.GetBounds delegate.</summary>
//		/// <typeparam name=""T"">The generic type to get the bounds of.</typeparam>
//		{__(@"/// <typeparam name=""A1"">The generic type of the 1 dimension.</typeparam>...")}
//		/// <param name=""getBoundings"">The Omnitree.GetBoundings to convert into a Omnitree.GetBounds.</param>
//		/// <returns>The converted Omnitree.GetBounds delegate.</returns>
//		public static GetBounds<T, {__("A1...")}> ConvertToGetBounds<T, {__("A1...")}>(GetBoundings<T, {__("A1...")}> getBoundings) =>
//			(T item, {__("out Bound<A1> min1, out Bound<A1> max1...")}) =>
//			{{
//				getBoundings(item,
//					{__("out A1 min1a, out A1 max1a...")});
//				{__("min1 = min1a; max1 = max1a;...")}
//			}};

			
//");



//				#region HIDE

//				// End Dimension
//				file.AppendLine(
//$@"		#endregion {i} Dimensional
//");
//			}
//			file.AppendLine($@"
//		#endregion Spacial Types (Bound, Vector, Bounds), Location/Bounding Delegates, And Dimensional Helper Methods

//	}}
//}}");

//			#endregion


			///// <summary>Checks a node for inclusion (overlap) between two bounds.</summary>
			///// <returns>True if the spaces overlap; False if not.</returns>
			//public static bool InclusionCheck<<#= chain_AxisX #>>(Omnitree.Bounds<<#= chain_AxisX #>> a, Omnitree.Bounds<<#= chain_AxisX #>> b,
			//			<#= chain_Compare_AxisX_compareX #>) =>
			//<# for (int j = 1; j <= i; j++) { #>
			//			a.Max <#= j #>.Exists && b.Min<#= j #>.Exists && compare<#= j #>(a.Max<#= j #>.Value, b.Min<#= j #>.Value) == CompareResult.Less ? false :
			//			a.Min <#= j #>.Exists && b.Max<#= j #>.Exists && compare<#= j #>(a.Min<#= j #>.Value, b.Max<#= j #>.Value) == CompareResult.Greater ? false :
			//<# } #>
			//			true;

			///// <summary>Checks if a space encapsulates a point.</summary>
			///// <returns>True if the space encapsulates the point; False if not.</returns>
			//public static bool EncapsulationCheck<<#= chain_AxisX #>>(Omnitree.Bounds<<#= chain_AxisX #>> bounds, Omnitree.Vector<<#= chain_AxisX #>> vector,
			//			<#= chain_Compare_AxisX_compareX #>) =>
			//			// if the location is not outside the bounds, it must be inside
			//<# for (int j = 1; j <= i; j++) { #>
			//			bounds.Min <#= j #>.Exists && compare<#= j #>(vector.Axis<#= j #>, bounds.Min<#= j #>.Value) == CompareResult.Less ? false :
			//			bounds.Max <#= j #>.Exists && compare<#= j #>(vector.Axis<#= j #>, bounds.Max<#= j #>.Value) == CompareResult.Greater ? false :
			//<# } #>
			//			true;

			///// <summary>Checks if a space (left) encapsulates another space (right).</summary>
			///// <returns>True if the left space encapsulates the right; False if not.</returns>
			//public static bool EncapsulationCheck<<#= chain_AxisX #>>(Omnitree.Bounds<<#= chain_AxisX #>> a, Omnitree.Bounds<<#= chain_AxisX #>> b,
			//			<#= chain_Compare_AxisX_compareX #>) =>
			//			(a.Min1.Exists && !b.Min1.Exists)
			//<# for (int j = 2; j <= i; j++) { #>
			//			|| (a.Min <#= j #>.Exists && !b.Min<#= j #>.Exists)
			//<# } #>
			//			? false :
			//	(a.Max1.Exists && !b.Max1.Exists)
			//<# for (int j = 2; j <= i; j++) { #>
			//			|| (a.Max <#= j #>.Exists && !b.Max<#= j #>.Exists)
			//<# } #>
			//			? false :
			//<# for (int j = 1; j <= i; j++) { #>
			//			b.Min <#= j #>.Exists && a.Min<#= j #>.Exists && compare<#= j #>(a.Min<#= j #>.Value, b.Min<#= j #>.Value) != CompareResult.Less ? false :
			//			b.Max <#= j #>.Exists && a.Max<#= j #>.Exists && compare<#= j #>(a.Max<#= j #>.Value, b.Max<#= j #>.Value) != CompareResult.Greater ? false :
			//<# } #>
			//			true;

			///// <summary>Checks for equality between two locations.</summary>
			///// <returns>True if equal; False if not;</returns>
			//public static bool EqualsCheck<<#= chain_AxisX #>>(Omnitree.Vector<<#= chain_AxisX #>> a, Omnitree.Vector<<#= chain_AxisX #>> b,
			//			<#= chain_Equate_AxisX_equateX #>) =>
			//<# for (int j = 1; j <= i; j++) { #>
			//			!equate <#= j #>(a.Axis<#= j #>, b.Axis<#= j #>) ? false :
			//<# } #>
			//			true;

			//		/// <summary>Checks if a bounds straddles a point if the point extended as a plane along each dimension.</summary>
			//<# for (int j = 1; j <= i; j++) { #>
			//		/// <typeparam name="Axis<#= j #>">The generic type of the <#= j #> dimension.</typeparam>
			//<# } #>
			//		/// <param name="bounds">The bounds to determine if it straddles the extended point.</param>
			//		/// <param name="vector">The point representing an extended plan along each axis.</param>
			//<# for (int j = 1; j <= i; j++) { #>
			//		/// <param name="compare<#= j #>">The delegate for comparing values along the the <#= j #> dimension.</param>
			//<# } #>
			//		/// <returns>True if the extended point was straddled or false if not.</returns>
			//public static bool StraddlesLines<<#= chain_AxisX #>>(Omnitree.Bounds<<#= chain_AxisX #>> bounds, Omnitree.Vector<<#= chain_AxisX #>> vector,
			//			<#= chain_Compare_AxisX_compareX #>) =>
			//<# for (int j = 1; j <= i; j++) { #>
			//			(!bounds.Min <#= j #>.Exists || (bounds.Min<#= j #>.Exists && compare<#= j #>(bounds.Min<#= j #>.Value, vector.Axis<#= j #>) != CompareResult.Greater)) &&
			//			(!bounds.Max <#= j #>.Exists || (bounds.Max<#= j #>.Exists && compare<#= j #>(bounds.Max<#= j #>.Value, vector.Axis<#= j #>) != CompareResult.Less)) ? true :
			//<# } #>
			//			false;

			//		/// <summary>Removes all occurences of a value from the omnitree.</summary>
			//		/// <typeparam name="T">The generic value type being stored in the omnitree.</typeparam>
			//<# for (int j = 1; j <= i; j++) { #>
			//		/// <typeparam name="Axis<#= j #>">The geneic type of the <#= j #>D axis.</typeparam>
			//<# } #>
			//		/// <param name="omnitree">The omnitree to remove from.</param>
			//		/// <param name="removal">The value to have all occurences removed.</param>
			//public static void Remove<T, <#= chain_AxisX #>>(this IOmnitreePoints<T, <#= chain_AxisX #>> omnitree, T removal) => Remove(omnitree, removal, Equate.Default);

			//		/// <summary>Removes all occurences of a value from the omnitree.</summary>
			//		/// <typeparam name="T">The generic value type being stored in the omnitree.</typeparam>
			//<# for (int j = 1; j <= i; j++) { #>
			//		/// <typeparam name="Axis<#= j #>">The geneic type of the <#= j #>D axis.</typeparam>
			//<# } #>
			//		/// <param name="omnitree">The omnitree to remove from.</param>
			//		/// <param name="removal">The value to have all occurences removed.</param>
			//		/// <param name="equate">The delegate for checking for equality.</param>
			//public static void Remove<T, <#= chain_AxisX #>>(this IOmnitreePoints<T, <#= chain_AxisX #>> omnitree, T removal, Func<T, T, bool> equate)
			//		{
			//<# for (int j = 1; j <= i; j++) { #>
			//			Axis<#= j #> axis<#= j #>;
			//<# } #>
			//			omnitree.Locate(removal, out axis1
			//<# for (int j = 2; j <= i; j++) { #>
			//				, out axis<#= j #>
			//<# } #>
			//				);
			//	omnitree.Remove(
			//<# for (int j = 1; j <= i; j++) { #>
			//				axis<#= j #>,
			//<# } #>
			//				x => equate(x, removal));
			//}

			//		/// <summary>Removes all occurences of a value from the omnitree.</summary>
			//		/// <typeparam name="T">The generic value type being stored in the omnitree.</typeparam>
			//<# for (int j = 1; j <= i; j++) { #>
			//		/// <typeparam name="Axis<#= j #>">The geneic type of the <#= j #>D axis.</typeparam>
			//<# } #>
			//		/// <param name="omnitree">The omnitree to remove from.</param>
			//		/// <param name="removal">The value to have all occurences removed.</param>
			//public static void Remove<T, <#= chain_AxisX #>>(this IOmnitreeBounds<T, <#= chain_AxisX #>> omnitree, T removal) => Remove(omnitree, removal, Equate.Default);

			//		/// <summary>Removes all occurences of a value from the omnitree.</summary>
			//		/// <typeparam name="T">The generic value type being stored in the omnitree.</typeparam>
			//<# for (int j = 1; j <= i; j++) { #>
			//		/// <typeparam name="Axis<#= j #>">The geneic type of the <#= j #>D axis.</typeparam>
			//<# } #>
			//		/// <param name="omnitree">The omnitree to remove from.</param>
			//		/// <param name="removal">The value to have all occurences removed.</param>
			//		/// <param name="equate">The delegate for checking for equality.</param>
			//public static void Remove<T, <#= chain_AxisX #>>(this IOmnitreeBounds<T, <#= chain_AxisX #>> omnitree,T removal, Func<T, T, bool> equate)
			//		{
			//<# for (int j = 1; j <= i; j++) { #>
			//			Omnitree.Bound<Axis<#= j #>> min<#= j #>; Omnitree.Bound<Axis<#= j #>> max<#= j #>;
			//<# } #>
			//			omnitree.GetBounds(removal, out min1, out max1
			//<# for (int j = 2; j <= i; j++) { #>
			//				, out min<#= j #>, out max<#= j #>
			//<# } #>
			//				);
			//	omnitree.RemoveOverlapped(min1, max1
			//<# for (int j = 2; j <= i; j++) { #>
			//				, min<#= j #>, max<#= j #>
			//<# } #>
			//				, x => equate(x, removal));
			//}

			//		#endregion
			//<# } #>

			//		#endregion
			//	}

			//	#region Omnitree
			//<# foreach (int i in dimensionsToGenerate) {
			//// ------------------------------------------------------------------------------------------------------------------------------ 
			//// PARAMETER/ARGUMENT CHAINS
			//string chain_AxisX = "Axis1"; for (int j = 2; j <= i; j++) { chain_AxisX += ", Axis" + j; }
			//string chain_axisX = "axis1"; for (int j = 2; j <= i; j++) { chain_axisX += ", axis" + j; }
			//string chain_AxisX_axisX = "Axis1 axis1"; for (int j = 2; j <= i; j++) { chain_AxisX_axisX += ", Axis" + j + " axis" + j; }
			//string chain_AxisX_minX_AxisX_maxX = "Axis1 min1, Axis1 max1"; for (int j = 2; j <= i; j++) { chain_AxisX_minX_AxisX_maxX += ", Axis" + j + " min" + j + ", Axis" + j + " max" + j; }
			//string chain_BoundAxisX_minX_BoundAxisX_maxX = "Omnitree.Bound<Axis1> min1, Omnitree.Bound<Axis1> max1"; for (int j = 2; j <= i; j++) { chain_BoundAxisX_minX_BoundAxisX_maxX += ", Omnitree.Bound<Axis" + j + "> min" + j + ", Omnitree.Bound<Axis" + j + "> max" + j; }
			//string chain_BoundAxisX_axisX = "Omnitree.Bound<Axis1> axis1"; for (int j = 2; j <= i; j++) { chain_BoundAxisX_axisX += ", Omnitree.Bound<Axis" + j + "> axis" + j; }
			//string chain_minX_maxX = "min1, max1"; for (int j = 2; j <= i; j++) { chain_minX_maxX += ", min" + j + ", max" + j; }
			//string chain_axisX_axisX = "axis1, axis1"; for (int j = 2; j <= i; j++) { chain_axisX_axisX += ", axis" + j + ", axis" + j; }
			////string child_index_type; if (i <= 30) { child_index_type = "int"; } else if (i <= 60) { child_index_type = "long"; } else { child_index_type = "BigInteger"; }
			//// DOCUMENTATION
			//string documentation_AxisX_axisX = string.Empty; for (int j = 1; j <= i; j++) { documentation_AxisX_axisX += "\n\t\t/// <param name=\"axis" + j + "\">The coordinate along the " + j + "D axis.</param>"; }
			//documentation_AxisX_axisX = documentation_AxisX_axisX.Trim();
			//string documentation_AxisX_minX_AxisX_maxX = string.Empty; for (int j = 1; j <= i; j++) { documentation_AxisX_minX_AxisX_maxX += "\n\t\t/// <param name=\"min" + j + "\">The minimum coordinate of the space along the " + j + " axis.</param>\n\t\t/// <param name=\"max" + j + "\">The maximum coordinate of the space along the " + j + " axis.</param>"; }
			//documentation_AxisX_minX_AxisX_maxX = documentation_AxisX_minX_AxisX_maxX.Trim();
			//string documentation_axisX = string.Empty; for (int j = 1; j <= i; j++) { documentation_axisX += "\n\t\t/// <param name=\"axis" + j + "\">The axis of the removal along the  " + j + "D axis.</param>"; }
			//documentation_axisX = documentation_axisX.Trim();
			//// ------------------------------------------------------------------------------------------------------------------------------ #>

			//#region <#= i #> Dimensional

			///// <summary>Inheritance base for <#= i #>D omnitrees.</summary>
			///// <typeparam name="T">The type of items to store in the omnitree.</typeparam>
			//<# for (int j = 1; j <= i; j++) { #>
			//	/// <typeparam name="Axis<#= j #>">The type <#= j #>D axis.</typeparam>
			//<# } #>
			//	public interface IOmnitree<T, <#= chain_AxisX #>> : IOmnitree<T> { }

			//	#endregion
			//<# } #>

			//	#endregion

			//	#region OmnitreePoints
			//<# foreach (int i in dimensionsToGenerate)
			//{
			//	// ------------------------------------------------------------------------------------------------------------------------------ 
			//	// PARAMETER/ARGUMENT CHAINS
			//	string chain_AxisX = "Axis1"; for (int j = 2; j <= i; j++) { chain_AxisX += ", Axis" + j; }
			//string chain_axisX = "axis1"; for (int j = 2; j <= i; j++) { chain_axisX += ", axis" + j; }
			//string chain_AxisX_axisX = "Axis1 axis1"; for (int j = 2; j <= i; j++) { chain_AxisX_axisX += ", Axis" + j + " axis" + j; }
			//string chain_AxisX_minX_AxisX_maxX = "Axis1 min1, Axis1 max1"; for (int j = 2; j <= i; j++) { chain_AxisX_minX_AxisX_maxX += ", Axis" + j + " min" + j + ", Axis" + j + " max" + j; }
			//string chain_BoundAxisX_minX_BoundAxisX_maxX = "Omnitree.Bound<Axis1> min1, Omnitree.Bound<Axis1> max1"; for (int j = 2; j <= i; j++) { chain_BoundAxisX_minX_BoundAxisX_maxX += ", Omnitree.Bound<Axis" + j + "> min" + j + ", Omnitree.Bound<Axis" + j + "> max" + j; }
			//string chain_BoundAxisX_axisX = "Omnitree.Bound<Axis1> axis1"; for (int j = 2; j <= i; j++) { chain_BoundAxisX_axisX += ", Omnitree.Bound<Axis" + j + "> axis" + j; }
			//string chain_minX_maxX = "min1, max1"; for (int j = 2; j <= i; j++) { chain_minX_maxX += ", min" + j + ", max" + j; }
			//string chain_axisX_axisX = "axis1, axis1"; for (int j = 2; j <= i; j++) { chain_axisX_axisX += ", axis" + j + ", axis" + j; }
			//string child_index_type; if (i <= 30) { child_index_type = "int"; } else if (i <= 60) { child_index_type = "long"; } else { child_index_type = "BigInteger"; }
			//// DOCUMENTATION
			//string documentation_AxisX_axisX = string.Empty; for (int j = 1; j <= i; j++) { documentation_AxisX_axisX += "\n\t\t/// <param name=\"axis" + j + "\">The coordinate along the " + j + "D axis.</param>"; }
			//documentation_AxisX_axisX = documentation_AxisX_axisX.Trim();
			//string documentation_AxisX_minX_AxisX_maxX = string.Empty; for (int j = 1; j <= i; j++) { documentation_AxisX_minX_AxisX_maxX += "\n\t\t/// <param name=\"min" + j + "\">The minimum coordinate of the space along the " + j + " axis.</param>\n\t\t/// <param name=\"max" + j + "\">The maximum coordinate of the space along the " + j + " axis.</param>"; }
			//documentation_AxisX_minX_AxisX_maxX = documentation_AxisX_minX_AxisX_maxX.Trim();
			//string documentation_axisX = string.Empty; for (int j = 1; j <= i; j++) { documentation_axisX += "\n\t\t/// <param name=\"axis" + j + "\">The axis of the removal along the  " + j + "D axis.</param>"; }
			//documentation_axisX = documentation_axisX.Trim();
			//// ------------------------------------------------------------------------------------------------------------------------------ #>

			//#region <#= i #> Dimensional

			///// <summary>Inheritance base for <#= i #>D omnitrees that store points.</summary>
			///// <typeparam name="T">The type of items to store in the omnitree.</typeparam>
			//<# for (int j = 1; j <= i; j++) { #>
			//	/// <typeparam name="Axis<#= j #>">The type <#= j #>D axis.</typeparam>
			//<# } #>
			//	public interface IOmnitreePoints<T, <#= chain_AxisX #>> : IOmnitree<T, <#= chain_AxisX #>>
			//	{
			//		#region Properties

			//		/// <summary>Steps through the values at a given location.</summary>
			//		<#= documentation_AxisX_axisX #>

			//		/// <returns>A Stepper of the items at the given coordinates.</returns>
			//		Action<Action<T>> this[<#= chain_AxisX_axisX #>] { get; }

			//		/// <summary>The number of dimensions in this tree.</summary>
			//		int Dimensions { get; }

			//	/// <summary>The delegate being used by the omnitree to locate items in <#= i #>D space.</summary>
			//	Omnitree.Location<T, Axis1
			//<# for (int j = 2; j <= i; j++) { #>
			//			, Axis<#= j #>
			//<# } #>
			//			> Locate { get; }

			//		#endregion

			//#region Methods

			//		/// <summary>Counts the number of items in a sub space.</summary>
			//		<#= documentation_AxisX_minX_AxisX_maxX #>
			//		/// <returns>The number of items in the provided sub space.</returns>
			//		int CountSubSpace(<#= chain_BoundAxisX_minX_BoundAxisX_maxX #>);

			//		/// <summary>Iterates through the entire tree and ensures each item is in the proper leaf.</summary>
			//		void Update();
			//		/// <summary>Iterates through the provided dimensions and ensures each item is in the proper leaf.</summary>
			//		<#= documentation_AxisX_minX_AxisX_maxX #>
			//		void Update(<#= chain_BoundAxisX_minX_BoundAxisX_maxX #>);

			//		/// <summary>Removes all the items in a given space.</summary>
			//		<#= documentation_AxisX_axisX #>
			//		void Remove(<#= chain_AxisX_axisX #>);
			//		/// <summary>Removes all the items in a given space.</summary>
			//		<#= documentation_AxisX_minX_AxisX_maxX #>
			//		void Remove(<#= chain_BoundAxisX_minX_BoundAxisX_maxX #>);
			//		/// <summary>Removes all the items in a given space where equality is met.</summary>
			//		<#= documentation_AxisX_axisX #>
			//		/// <param name="where">The equality constraint of the removal.</param>
			//		void Remove(<#= chain_AxisX_axisX #>, Predicate<T> where);
			//		/// <summary>Removes all the items in a given space where predicate is met.</summary>
			//		<#= documentation_AxisX_minX_AxisX_maxX #>
			//		/// <param name="where">The predicate constraint of the removal.</param>
			//		void Remove(<#= chain_BoundAxisX_minX_BoundAxisX_maxX #>, Predicate<T> where);

			//		/// <summary>Performs and specialized traversal of the structure and performs a delegate on every node within the provided dimensions.</summary>
			//		/// <param name="step">The step function to perform on all items in the tree within the given bounds.</param>
			//		<#= documentation_AxisX_minX_AxisX_maxX #>
			//		void Stepper(Step < T > step, <#= chain_BoundAxisX_minX_BoundAxisX_maxX #>);
			//		/// <summary>Performs and specialized traversal of the structure and performs a delegate on every node within the provided dimensions.</summary>
			//		/// <param name="step">The step function to perform on all items in the tree within the given bounds.</param>
			//		<#= documentation_AxisX_minX_AxisX_maxX #>
			//		StepStatus Stepper(StepBreak < T > step, <#= chain_BoundAxisX_minX_BoundAxisX_maxX #>);
			//		/// <summary>Performs and specialized traversal of the structure and performs a delegate on every node within the provided dimensions.</summary>
			//		/// <param name="step">The step function to perform on all items in the tree within the given bounds.</param>
			//		<#= documentation_AxisX_axisX #>
			//		void Stepper(Step < T > step, <#= chain_AxisX_axisX #>);
			//		/// <summary>Performs and specialized traversal of the structure and performs a delegate on every node within the provided dimensions.</summary>
			//		/// <param name="step">The step function to perform on all items in the tree within the given bounds.</param>
			//		<#= documentation_AxisX_axisX #>
			//		StepStatus Stepper(StepBreak < T > step, <#= chain_AxisX_axisX #>);

			//		#endregion
			//	}

			//	/// <summary>Omnitree that stores points along <#= i #> dimensions implemented as a linked tree.</summary>
			//	/// <typeparam name="T">The type of items to store in the omnitree.</typeparam>
			//<# for (int j = 1; j <= i; j++) { #>
			//	/// <typeparam name="Axis<#= j #>">The type <#= j #>D axis.</typeparam>
			//<# } #>
			//	public class OmnitreePointsLinked<T, <#= chain_AxisX #>> : IOmnitreePoints<T, <#= chain_AxisX #>>
			//	{
			//	internal const int _dimensions = <#= i #>;
			//		internal static <#= child_index_type #> _children_per_node = (<#= child_index_type #>)BigInteger.Pow(2, <#= i #>);

			//		internal Node _top;
			//	internal int _naturalLogLower = 1; // caching the next time to calculate loads (lower count)
			//	internal int _naturalLogUpper = -1; // caching the next time to calculate loads (upper count)
			//	internal int _load; // ln(count); min = _defaultLoad
			//	internal Omnitree.Location<T, Axis1
			//<# for (int j = 2; j <= i; j++) { #>
			//			, Axis<#= j #>
			//<# } #>
			//			> _locate;
			//<# for (int j = 1; j <= i; j++) { #>
			//		internal bool _defaultCompare<#= j #>;
			//		internal Compare<Axis<#= j #>> _compare<#= j #>;
			//<# } #>
			//<# for (int j = 1; j <= i; j++) { #>
			//		internal Omnitree.SubdivisionOverride<T, Axis<#= j #>, Omnitree.Bounds<<#= chain_AxisX #>>> _subdivisionOverride<#= j #>;
			//<# } #>

			//		#region Nested Types

			//		/// <summary>Can be a leaf or a branch.</summary>
			//		internal abstract class Node
			//	{
			//		internal Omnitree.Bounds<<#= chain_AxisX #>> Bounds;
			//			internal Branch Parent;
			//		internal <#= child_index_type #> Index;
			//			internal int Count;

			//		/// <summary>The depth this node is located in the Omnitree.</summary>
			//		internal int Depth
			//		{
			//			get
			//			{
			//				int depth = -1;
			//				for (Node node = this; !(node is null); node = node.Parent)
			//					depth++;
			//				return depth;
			//			}
			//		}

			//		/// <summary>Constructs a node.</summary>
			//		/// <param name="bounds">The bounds of this node.</param>
			//		/// <param name="parent">The parent of this node.</param>
			//		/// <param name="index">The number of elements stored in this node and its children.</param>
			//		internal Node(Omnitree.Bounds<<#= chain_AxisX #>> bounds, Branch parent, <#= child_index_type #> index)
			//			{
			//			Bounds = bounds;
			//			Parent = parent;
			//			Index = index;
			//		}

			//		internal Node(Node nodeToClone)
			//		{
			//			this.Bounds = nodeToClone.Bounds;
			//			this.Parent = nodeToClone.Parent;
			//			this.Index = nodeToClone.Index;
			//			this.Count = nodeToClone.Count;
			//		}

			//		internal abstract Node Clone();
			//	}

			//	/// <summary>A branch in the tree. Only contains nodes.</summary>
			//	internal class Branch : Node
			//	{
			//		internal Node[] Children;
			//		internal Omnitree.Vector<<#= chain_AxisX #>> PointOfDivision;

			//			/// <summary>Gets child by index.</summary>
			//			/// <param name="child_index">The index of the child to get.</param>
			//			/// <returns>The child of the given index or null if non-existent.</returns>
			//			internal Node this[<#= child_index_type #> child_index]
			//			{
			//				get
			//				{
			//					if (Children is null)
			//						return null;
			//					if (Children.Length == OmnitreePointsLinked<T, <#= chain_AxisX #>>._children_per_node)
			//						return Children[(int)child_index];
			//					foreach (Node node in Children)
			//						if (node.Index == child_index)
			//							return node;
			//					return null;
			//				}
			//	set
			//				{
			//					// This error check should be unnecessary... but fuck it... might as well
			//					if (value.Index != child_index)
			//						throw new System.Exception("Bug in Omnitree (index/property mis-match when setting a child on a branch)");

			//					// no children yet
			//					if (Children is null)
			//					{
			//						Children = Ɐ(value);
			//						return;
			//					}
			//					// max children overwrite
			//else if (this.Children.Length == OmnitreePointsLinked < T, <#= chain_AxisX #>>._children_per_node)
			//					{
			//	Children[(int)child_index] = value;
			//	return;
			//}
			//// non-max child overwrite
			//for (int i = 0; i < Children.Length; i++)
			//	if (Children[i].Index == child_index)
			//	{
			//		Children[i] = value;
			//		return;
			//	}
			//// new child
			//Node[] newArray = new Node[Children.Length + 1];
			//if (newArray.Length == OmnitreePointsLinked < T, <#= chain_AxisX #>>._children_per_node)
			//					{
			//	// new child resulting in a max children branch (sorting required)
			//	for (int i = 0; i < Children.Length; i++)
			//	{
			//		newArray[(int)Children[i].Index] = Children[i];
			//	}
			//	newArray[(int)value.Index] = value;
			//}
			//					else
			//{
			//	// new child resulting in a non-max children branch
			//	Array.Copy(Children, newArray, Children.Length);
			//	newArray[newArray.Length - 1] = value;
			//}
			//this.Children = newArray;
			//				}
			//			}

			//			internal Branch(Omnitree.Vector<<#= chain_AxisX #>> pointOfDivision, Omnitree.Bounds<<#= chain_AxisX #>> bounds, Branch parent, <#= child_index_type #> index)
			//				: base(bounds, parent, index)
			//			{
			//	this.PointOfDivision = pointOfDivision;
			//}

			//internal Branch(Branch branchToClone) : base(branchToClone)
			//			{
			//	Children = branchToClone.Children.Clone() as Node[];
			//	PointOfDivision = branchToClone.PointOfDivision;
			//}

			//internal override Node Clone() =>
			//	new Branch(this);
			//		}

			//		/// <summary>A branch in the tree. Only contains items.</summary>
			//		internal class Leaf : Node
			//{
			//	internal class Node
			//	{
			//		internal T Value;
			//		internal Leaf.Node Next;

			//		internal Node(T value, Leaf.Node next)
			//		{
			//			Value = value;
			//			Next = next;
			//		}
			//	}

			//	internal Leaf.Node Head;

			//	internal Leaf(Omnitree.Bounds<<#= chain_AxisX #>> bounds, Branch parent, <#= child_index_type #> index)
			//				: base(bounds, parent, index)
			//			{ }

			//	internal Leaf(Leaf leaf) : base(leaf)
			//	{
			//		Head = new Node(leaf.Head.Value, null);
			//		Node a = Head;
			//		Node b = leaf.Head;
			//		while (!(b is null))
			//		{
			//			a.Next = new Node(b.Next.Value, null);
			//			a = a.Next;
			//			b = b.Next;
			//		}
			//	}

			//	internal void Add(T addition)
			//	{
			//		Head = new Leaf.Node(addition, Head);
			//		this.Count++;
			//	}

			//	internal override OmnitreePointsLinked<T, <#= chain_AxisX #>>.Node Clone() =>
			//				new Leaf(this);
			//}

			//#endregion

			//#region Constructors

			///// <summary>This constructor is for cloning purposes</summary>
			//internal OmnitreePointsLinked(OmnitreePointsLinked<T, <#= chain_AxisX #>> omnitree)
			//		{
			//			this._top = omnitree._top.Clone();
			//this._load = omnitree._load;
			//this._locate = omnitree._locate;
			//<# for (int j = 1; j <= i; j++) { #>
			//			this._defaultCompare <#= j #> = omnitree._defaultCompare<#= j #>;
			//			this._compare <#= j #> = omnitree._compare<#= j #>;
			//<# } #>
			//<# for (int j = 1; j <= i; j++) { #>
			//			this._subdivisionOverride <#= j #> = omnitree._subdivisionOverride<#= j #>;
			//<# } #>
			//		}

			//		internal OmnitreePointsLinked(
			//			Omnitree.Location<T, <#= chain_AxisX #>> locate,
			//<# for (int j = 1; j <= i; j++) { #>
			//			bool defaultCompare<#= j #>,
			//			Compare<Axis<#= j #>> compare<#= j #>,
			//<# } #>
			//			Omnitree.SubdivisionOverride<T, Axis1, Omnitree.Bounds<<#= chain_AxisX #>>> subdivisionOverride1
			//<# for (int j = 2; j <= i; j++) { #>,
			//			Omnitree.SubdivisionOverride<T, Axis<#= j #>, Omnitree.Bounds<<#= chain_AxisX #>>> subdivisionOverride<#= j #>
			//<# } #>
			//			)
			//{
			//	if (locate is null)
			//	{
			//		throw new ArgumentNullException(nameof(locate));
			//	}
			//<# for (int j = 1; j <= i; j++) { #>
			//			if (compare <#= j #> is null)
			//			{
			//		throw new ArgumentNullException(nameof(compare <#= j #>));
			//			}

			//<# } #>
			//			this._locate = locate;
			//<# for (int j = 1; j <= i; j++) { #>
			//			this._defaultCompare <#= j #> = defaultCompare<#= j #>;
			//			this._compare <#= j #> = compare<#= j #>;
			//<# } #>
			//<# for (int j = 1; j <= i; j++) { #>
			//			this._subdivisionOverride <#= j #> = subdivisionOverride<#= j #>;
			//<# } #>
			//			this._top = new Leaf(Omnitree.Bounds <<#= chain_AxisX #>>.None, null, -1);
			//			Omnitree.ComputeLoads(_top.Count, ref _naturalLogLower, ref _naturalLogUpper, ref _load);
			//}

			//		/// <summary>Constructs a new <#= i #>D omnitree that stores points.</summary>
			//		/// <param name="locate">The delegate for locating items in <#= i #>D space.</param>
			//<# for (int j = 1; j <= i; j++) { #>

			//		/// <param name="compare<#= j #>">The delegate for comparing values along the <#= j #>D axis.</param>
			//<# } #>
			//<# for (int j = 1; j <= i; j++) { #>

			//		/// <param name="subdivisionOverride<#= j #>">The subdivision overide to be used when splitting the <#= j #> dimension.</param>
			//<# } #>
			//		public OmnitreePointsLinked(
			//			Omnitree.Location<T, <#= chain_AxisX #>> locate,
			//<# for (int j = 1; j <= i; j++) { #>
			//			Compare<Axis<#= j #>> compare<#= j #> = null,
			//<# } #>
			//			Omnitree.SubdivisionOverride<T, Axis1, Omnitree.Bounds<<#= chain_AxisX #>>> subdivisionOverride1 = null
			//<# for (int j = 2; j <= i; j++) { #>,
			//			Omnitree.SubdivisionOverride<T, Axis<#= j #>, Omnitree.Bounds<<#= chain_AxisX #>>> subdivisionOverride<#= j #> = null
			//<# } #>
			//			)
			//			: this(
			//				locate,
			//<# for (int j = 1; j <= i; j++) { #>
			//				compare <#= j #> is null ? true : false,
			//				compare <#= j #> ?? Compare.Default,
			//<# } #>
			//				subdivisionOverride1
			//<# for (int j = 2; j <= i; j++) { #>,
			//				subdivisionOverride <#= j #>
			//<# } #>
			//				) { }

			//		#endregion

			//#region Properties

			///// <summary>Steps through all the items at a given coordinate.</summary>
			//<# for (int j = 1; j <= i; j++) { #>
			//		/// <param name="axis<#= j #>">The coordinate along axis <#= j #>.</param>
			//<# } #>
			//		/// <returns>The stepper for the items at the given coordinate.</returns>
			//public Action<Action<T>> this[<#= chain_AxisX_axisX #>] =>
			//			step => Stepper(step, <#= chain_axisX #>);

			//		/// <summary>The number of dimensions in this tree.</summary>
			//public int Dimensions { get { return _dimensions; } }

			///// <summary>The location function the Omnitree is using.</summary>
			//public Omnitree.Location<T, <#= chain_AxisX #>> Locate { get { return this._locate; } }

			//<# for (int j = 1; j <= i; j++) { #>
			//		/// <summary>The comparison function the Omnitree is using along the <#= j #>D axis.</summary>
			//		public Compare<Axis<#= j #>> Compare<#= j #> { get { return this._compare<#= j #>; } }
			//<# } #>

			//		/// <summary>The current number of items in the tree.</summary>
			//		public int Count { get { return this._top.Count; } }

			//internal delegate void MaxDepthFinder(Node node, int current_depth, ref int max_depth);
			///// <summary>Finds the current maximum depth of the tree. NOT AN O(1) OPERATION. Intended for educational purposes only.</summary>
			//public int MaxDepth
			//{
			//	get
			//	{
			//		MaxDepthFinder maxDepthFinder = null;
			//		maxDepthFinder =
			//			(Node node, int current_depth, ref int max_depth) =>
			//			{
			//				if (current_depth > max_depth)
			//					max_depth = current_depth;
			//				if (node is Branch)
			//					foreach (Node child in (node as Branch).Children)
			//						maxDepthFinder(child, current_depth + 1, ref max_depth);
			//			};
			//		int _max_depth = -1;
			//		maxDepthFinder(this._top, 0, ref _max_depth);
			//		return _max_depth;
			//	}
			//}

			//internal delegate void NodeCountFinder(Node node, ref int current_count);
			///// <summary>Counts the current number of nodes in the tree. NOT AN O(1) OPERATION. Intended for educational purposes only.</summary>
			//public int NodeCount
			//{
			//	get
			//	{
			//		NodeCountFinder nodeCountFinder = null;
			//		nodeCountFinder =
			//			(Node node, ref int current_count) =>
			//			{
			//				current_count++;
			//				if (node is Branch)
			//					foreach (Node child in (node as Branch).Children)
			//						nodeCountFinder(child, ref current_count);
			//			};

			//		int _current_count = 0;
			//		nodeCountFinder(this._top, ref _current_count);
			//		return _current_count;
			//	}
			//}

			//internal delegate void BranchCountFinder(Node node, ref int current_count);
			///// <summary>Counts the current number of branches in the tree. NOT AN O(1) OPERATION. Intended for educational purposes only.</summary>
			//public int BranchCount
			//{
			//	get
			//	{
			//		BranchCountFinder branchCountFinder = null;
			//		branchCountFinder =
			//			(Node node, ref int current_count) =>
			//			{
			//				if (node is Branch)
			//				{
			//					current_count++;
			//					foreach (Node child in (node as Branch).Children)
			//						branchCountFinder(child, ref current_count);
			//				}
			//			};

			//		int _current_count = 0;
			//		branchCountFinder(this._top, ref _current_count);
			//		return _current_count;
			//	}
			//}

			//internal delegate void LeafCountFinder(Node node, ref int current_count);
			///// <summary>Counts the current number of leaves in the tree. NOT AN O(1) OPERATION. Intended for educational purposes only.</summary>
			//public int LeafCount
			//{
			//	get
			//	{
			//		LeafCountFinder leafCountFinder = null;
			//		leafCountFinder =
			//			(Node node, ref int current_count) =>
			//			{
			//				if (node is Leaf)
			//					current_count++;
			//				else
			//					foreach (Node child in (node as Branch).Children)
			//						leafCountFinder(child, ref current_count);
			//			};

			//		int _current_count = 0;
			//		leafCountFinder(this._top, ref _current_count);
			//		return _current_count;
			//	}
			//}

			//		#endregion

			//#region Methods

			//#region Add

			//<
			//#if (false) { #>
			//#region Bulk

			////		public void Add(ArrayJagged<T> additions, bool allowMultithreading)
			////		{
			////			if (additions.Length > int.MaxValue)
			////				throw new System.Exception("The maximum size of the Omnitree was exceeded during bulk addition.");
			////
			////			if (this._top.Count != 0 || (int)additions.Length <= _load)
			////			{
			////				for (ulong i = 0; i < additions.Length; i++)
			////					this.Add(additions[i]);
			////			}
			////			else
			////			{
			////				// adjust the loads prior to additions
			////				Omnitree.ComputeLoads((int)additions.Length, ref _naturalLogLower, ref _naturalLogUpper, ref _load);
			////
			////				Branch new_top = new Branch(Omnitree.Vector<<#= chain_AxisX #>>.Default, Omnitree.Bounds<<#= chain_AxisX #>>.None, null, -1);
			////				new_top.Count = (int)additions.Length;
			////
			////
			//<# for (int j = 1; j <= i; j++) { #>
			////				// prepare data for median computations
			////				ArrayJagged<Axis<#= j #>> values<#= j #>;
			////				//IAsyncResult result<#= j #> = null;
			////				if (!(this._subdivisionOverride<#= j #> is null))
			////					values<#= j #> = null;
			////				else
			////				{
			////					values<#= j #> = null;
			////					Action action = () =>
			////					{
			////						values<#= j #> = new ArrayJagged<Axis<#= j #>>(additions.Length);
			////						for (ulong i = 0; i < additions.Length; i++)
			////							values<#= j #>[i] = LocateVector(additions[i]).Axis<#= j #>;
			////						Towel.Algorithms.Sort.Merge(this._compare<#= j #>, (int i) => { return values<#= j #>[(ulong)i]; }, (int i, Axis<#= j #> value) => { values<#= j #>[(ulong)i] = value; }, 0, (int)(additions.Length - 1));
			////					};
			////
			////					if (allowMultithreading)
			////					{
			////						//result<#= j #> = ParallelThread.Run(operation);
			////						throw new NotImplementedException();
			////					}
			////					else
			////					{
			////						action();
			////					}
			////				}
			////
			//<# } #>
			////
			////
			//<# for (int j = 1; j <= i; j++) { #>
			////				//if (this._subdivisionOverride<#= j #> is null && allowMultithreading)
			////				//	result<#= j #>.AsyncWaitHandle.WaitOne();
			////
			//<# } #>
			////
			////				// build the tree
			////				Add(new_top, 1, -1, additions.ToStepper(), (int)additions.Length, 
			//<# for (int j = 1; j <= i; j++) { #>int.MinValue, 
			//<# } #>(int)additions.Length, 
			//<# for (int j = 1; j <= i; j++) { #>(int index) => { return values<#= j #>[index]; }, 
			//<# } #>allowMultithreading);
			////				
			////				this._top = new_top;
			////			}
			////		}
			////
			////		public void Add(bool allowMultithreading, params T[] additions)
			////		{
			////			if (additions.Length > int.MaxValue)
			////				throw new System.Exception("The maximum size of the Omnitree was exceeded during bulk addition.");
			////
			////			if (this._top.Count != 0 || (int)additions.Length <= _load)
			////			{
			////				for (int i = 0; i < additions.Length; i++)
			////					this.Add(additions[i]);
			////			}
			////			else
			////			{
			////				// adjust the loads prior to additions
			////				Omnitree.ComputeLoads((int)additions.Length, ref _naturalLogLower, ref _naturalLogUpper, ref _load);
			////
			////				Branch new_top = new Branch(Omnitree.Vector<<#= chain_AxisX #>>.Default, Omnitree.Bounds<<#= chain_AxisX #>>.None, null, -1);
			////				new_top.Count = (int)additions.Length;
			////
			////
			//<# for (int j = 1; j <= i; j++) { #>
			////				// prepare data for median computations
			////				ArrayJagged<Axis<#= j #>> values<#= j #>;
			////				//IAsyncResult result<#= j #> = null;
			////				if (!(this._subdivisionOverride<#= j #> is null))
			////					values<#= j #> = null;
			////				else
			////				{
			////					values<#= j #> = null;
			////					Action action = () =>
			////					{
			////						values<#= j #> = new ArrayJagged<Axis<#= j #>>(additions.Length);
			////						for (int i = 0; i < additions.Length; i++)
			////							values<#= j #>[i] = LocateVector(additions[i]).Axis<#= j #>;
			////						Towel.Algorithms.Sort.Merge(this._compare<#= j #>, (int i) => { return values<#= j #>[(ulong)i]; }, (int i, Axis<#= j #> value) => { values<#= j #>[(ulong)i] = value; }, 0, (int)(additions.Length - 1));
			////					};
			////
			////					if (allowMultithreading)
			////					{
			////						//result<#= j #> = ParallelThread.Run(operation);
			////						throw new NotImplementedException();
			////					}
			////					else
			////					{
			////						action();
			////					}
			////				}
			////
			//<# } #>
			////
			////
			//<# for (int j = 1; j <= i; j++) { #>
			////				//if (this._subdivisionOverride<#= j #> is null && allowMultithreading)
			////				//	result<#= j #>.AsyncWaitHandle.WaitOne();
			////
			//<# } #>
			////
			////				// build the tree
			////				Add(new_top, 1, -1, additions.ToStepper(), additions.Length, 
			//<# for (int j = 1; j <= i; j++) { #>int.MinValue, 
			//<# } #>(int)additions.Length, 
			//<# for (int j = 1; j <= i; j++) { #>(int index) => { return values<#= j #>[index]; }, 
			//<# } #>allowMultithreading);
			////				
			////				this._top = new_top;
			////			}
			////		}
			////
			////		
			////		internal int Add(Branch parent, int depth, <#= child_index_type #> child, Action<Action<T>> additions, int parent_count, 
			//<# for (int j = 1; j <= i; j++) { #>int prevmed<#= j #>, 
			//<# } #>int initial_count, 
			//<# for (int j = 1; j <= i; j++) { #>GetIndex<Axis<#= j #>> values<#= j #>, 
			//<# } #>bool allowMultithreading)
			////		{
			//<# for (int j = 1; j <= i; j++) { #>
			////			Axis<#= j #> pointOfDivision<#= j #>;
			//<# } #>
			////
			//<# for (int j = 1; j <= i; j++) { #>
			////			int median_axis<#= j #> = -1;
			//<# } #>
			////			if (this._subdivisionOverride1 is null
			//<# for (int j = 2; j <= i; j++) { #> || this._subdivisionOverride<#= j #> is null
			//<# } #>)
			////				GetMedianIndexes(initial_count, child, depth, 
			//<# for (int j = 1; j <= i; j++) { #>prevmed<#= j #>, 
			//<# } #>out median_axis1
			//<# for (int j = 2; j <= i; j++) { #>, out median_axis<#= j #>
			//<# } #>);
			////
			//<# for (int j = 1; j <= i; j++) { #>
			////			if (!(this._subdivisionOverride<#= j #> is null))
			////				pointOfDivision<#= j #> = this._subdivisionOverride<#= j #>(parent.Bounds, additions);
			////			else
			////				pointOfDivision<#= j #> = values<#= j #>(median_axis<#= j #>);
			////
			//<# } #>
			////			parent.PointOfDivision = new Omnitree.Vector<<#= chain_AxisX #>>(pointOfDivision1
			//<# for (int j = 2; j <= i; j++) { #>, pointOfDivision<#= j #>
			//<# } #>);
			////
			////			// divide the values along the medians
			////			IMap<IList<T>, <#= child_index_type #>> collection_map = new MapHashLinked<IList<T>, <#= child_index_type #>>();
			////			additions((T value) => 
			////			{
			////				<#= child_index_type #> index = DetermineChildIndex(parent.PointOfDivision, LocateVector(value));
			////				IList<T> list = null;
			////				if (collection_map.TryGet(index, out list))
			////				{
			////					list.Add(value);
			////				}
			////				else
			////				{
			////					if (parent_count < 100000)
			////						list = new ListArray<T>();
			////					else
			////						list = new ListLinked<T>();
			////					collection_map.Add(index, list);
			////					list.Add(value);
			////				}
			////			});
			////
			////			//if (depth == 1 && allowMultithreading)
			////			//{
			////			//	// NOTE: Must assign placeholders before multithreading so that the threads do not overwrite each other
			////			//	collection_map.Keys((<#= child_index_type #> key) => { parent[key] = new Leaf(Omnitree.Bounds<<#= chain_AxisX #>>.None, parent, key); });
			////			//	IAsyncResult[] handles = new IAsyncResult[Environment.ProcessorCount];
			////			//	for (int i = 0; i < handles.Length; i++)
			////			//	{
			////			//		int multiTheadSafe_i = i; // used as catpure variable below making it multithread-safe
			////			//		handles[i] = ParallelThread.Run(() =>
			////			//		{
			////			//			Step.EveryNth<Link<IList<T>, <#= child_index_type #>>>(collection_map.Pairs, multiTheadSafe_i + 1)(
			////			//			(Link<IList<T>, <#= child_index_type #>> link) =>
			////			//				{
			////			//					ReversedChildBuilding(parent, link._2, depth, link._1.Stepper, link._1.Count, 
			//<# for (int j = 1; j <= i; j++) { #>median_axis<#= j #>, 
			//<# } #>initial_count, 
			//<# for (int j = 1; j <= i; j++) { #>values<#= j #>, 
			//<# } #>allowMultithreading);
			////			//				});
			////			//		});
			////			//	}
			////			//	
			////			//	foreach (IAsyncResult handle in handles)
			////			//	{
			////			//		handle.AsyncWaitHandle.WaitOne();
			////			//	}
			////			//}
			////			//else
			////			//{
			////				collection_map.Pairs((v, k) =>
			////				{ 
			////					ReversedChildBuilding(parent, k, depth, v.Stepper, v.Count, 
			//<# for (int j = 1; j <= i; j++) { #>median_axis<#= j #>, 
			//<# } #>initial_count, 
			//<# for (int j = 1; j <= i; j++) { #>values<#= j #>, 
			//<# } #>allowMultithreading);
			////				});
			////			//}
			////
			////			int count = 0;
			////			foreach (Node node in parent.Children)
			////				count += node.Count;
			////			return count;
			////		}
			////
			////		int ReversedChildBuilding(Branch parent, <#= child_index_type #> child_index, int depth, Action<Action<T>> additions, int count, 
			//<# for (int j = 1; j <= i; j++) { #>int prevmed<#= j #>, 
			//<# } #>int initial_count, 
			//<# for (int j = 1; j <= i; j++) { #>GetIndex<Axis<#= j #>> values<#= j #>, 
			//<# } #>bool allowMultithreading)
			////		{
			////			Omnitree.Bounds<<#= chain_AxisX #>> child_bounds = DetermineChildBounds(parent, child_index);
			////			if (depth >= _load || count <= _load)
			////			{
			////				Leaf new_leaf = new Leaf(child_bounds, parent, child_index);
			////				additions((T value) => { new_leaf.Add(value); });
			////				parent[new_leaf.Index] = new_leaf;
			////				return new_leaf.Count;
			////			}
			////			else
			////			{
			////				Branch new_branch = new Branch(Omnitree.Vector<<#= chain_AxisX #>>.Default, child_bounds, parent, child_index);
			////				parent[new_branch.Index] = new_branch;
			////				new_branch.Count = Add(new_branch, depth + 1, child_index, additions, count, 
			//<# for (int j = 1; j <= i; j++) { #>prevmed<#= j #>, 
			//<# } #>count, 
			//<# for (int j = 1; j <= i; j++) { #>values<#= j #>, 
			//<# } #>allowMultithreading);
			////				return new_branch.Count;
			////			}
			////		}
			////
			////		/// <summary>Gets the indeces of the median values at the given position during bulk additions.</summary>
			////		internal void GetMedianIndexes(int count, <#= child_index_type #> child_index, int depth, 
			//<# for (int j = 1; j <= i; j++) { #>int previous<#= j #>, 
			//<# } #>out int index1
			//<# for (int j = 2; j <= i; j++) { #>, out int index<#= j #>
			//<# } #>)
			////		{
			////			if (depth == 1)
			////			{
			//<# for (int j = 1; j <= i; j++) { #>
			////				index<#= j #> = (count - 1) / 2;
			//<# } #>
			////				return;
			////			}
			////
			////			int splits = Compute.Power(2, depth);
			////			int mid_child_range = count / splits;
			////
			//<# for (int j = i; j >= 1; j--) { #>
			////			if (child_index >= <#= (2 << (j - 1)) / 2 #>)
			////			{
			////				index<#= j #> = previous<#= j #> + mid_child_range;
			////				child_index -= <#= (2 << (j - 1)) / 2 #>;
			////			}
			////			else
			////			{
			////				index<#= j #> = previous<#= j #> - mid_child_range;
			////			}
			////
			//<# } #>
			////		}

			//#endregion

			//<# } #>

			//#region single

			//		/// <summary>Tries to add a value.</summary>
			//		/// <param name="value">The value to be added.</param>
			//		/// <param name="exception">The exception that occurred if the add failed.</param>
			//		/// <returns>True if successful or false if not.</returns>
			//		public bool TryAdd(T value, out Exception exception)
			//		{
			//			Add(value);
			//			exception = null;
			//			return true;
			//		}

			//		/// <summary>Adds an item to the tree.</summary>
			//		/// <param name="addition">The item to be added.</param>
			//		public void Add(T addition)
			//		{
			//			if (this._top.Count == int.MaxValue)
			//				throw new System.InvalidOperationException("(Count == int.MaxValue) max Omnitree size reached (change ints to longs if you need to).");

			//			// dynamic tree sizes
			//			Omnitree.ComputeLoads(_top.Count, ref _naturalLogLower, ref _naturalLogUpper, ref _load);

			//			Omnitree.Vector<<#= chain_AxisX #>> location = LocateVector(addition);

			//			// grow the first branch of the tree
			//			if (this._top is Leaf && (this._top as Leaf).Count >= _load)
			//			{
			//				Leaf top = this._top as Leaf;

			//				// create the new branch from the median values
			//				this._top = new Branch(DetermineMedians(top), Omnitree.Bounds<<#= chain_AxisX #>>.None, null, -1);

			//				// iterate through the elements and add them to the appropriate children
			//				for (Leaf.Node list = top.Head; !(list is null); list = list.Next)
			//					Add(list.Value, this._top, LocateVector(list.Value), 0);
			//			}

			//			this.Add(addition, this._top, location, 0);
			//		}

			//		/// <summary>Recursive version of the add function.</summary>
			//		/// <param name="addition">The item to be added.</param>
			//		/// <param name="node">The current node for tree trversal.</param>
			//		/// <param name="location">The location of the addition.</param>
			//		/// <param name="depth">The current depth of iteration.</param>
			//		internal void Add(T addition, Node node, Omnitree.Vector<<#= chain_AxisX #>> location, int depth)
			//		{
			//			if (node is Leaf)
			//			{
			//				Leaf leaf = node as Leaf;
			//				if (depth >= _load || !(leaf.Count >= _load))
			//				{
			//					leaf.Add(addition);
			//					return;
			//				}
			//				else
			//				{
			//					Branch parent = node.Parent;
			//					<#= child_index_type #> child_index = this.DetermineChildIndex(parent.PointOfDivision, location);
			//					Branch growth = new Branch(DetermineMedians(leaf), leaf.Bounds, parent, child_index);
			//					parent[child_index] = growth;
			//					for (Leaf.Node list = leaf.Head; !(list is null); list = list.Next)
			//					{
			//						Omnitree.Vector<<#= chain_AxisX #>> temp_location = LocateVector(list.Value);
			//						if (EncapsulationCheck(growth.Bounds, temp_location))
			//							Add(list.Value, growth, temp_location, depth);
			//						else
			//						{
			//							ReduceParentCounts(parent, 1);
			//							Add(list.Value, this._top, temp_location, depth);
			//						}
			//					}

			//					Add(addition, growth, location, depth);
			//					return;
			//				}
			//			}
			//			else
			//			{
			//				Branch branch = node as Branch;
			//				<#= child_index_type #> child_index = this.DetermineChildIndex(branch.PointOfDivision, location); // determine the child "index" (0 through 2^Dimensions) the addition belongs in
			//				Node child_node = branch[child_index];

			//				// null children in branches are just empty leaves
			//				if (child_node is null)
			//				{
			//					Leaf new_leaf = new Leaf(DetermineChildBounds(branch, child_index), branch, child_index);
			//					branch[child_index] = new_leaf;
			//					new_leaf.Add(addition);
			//				}
			//				else
			//					// child exists already, continue adding
			//					Add(addition, child_node, location, depth + 1);

			//				branch.Count++;
			//				return;
			//			}
			//		}

			//		internal Omnitree.Vector<<#= chain_AxisX #>> DetermineMedians(Leaf leaf)
			//		{

			//<# for (int j = 1; j <= i; j++) { #>
			//			Axis<#= j #> division<#= j #>;
			//			if (!(_subdivisionOverride<#= j #> is null))
			//			{
			//				division<#= j #> = _subdivisionOverride<#= j #>(leaf.Bounds, x =>
			//					{
			//						for (Leaf.Node node = leaf.Head; !(node is null); node = node.Next)
			//						{
			//							x(node.Value);
			//						}
			//					});
			//			}
			//			else
			//			{
			//				Axis<#= j #>[] values = new Axis<#= j #>[leaf.Count];
			//				Leaf.Node for_current = leaf.Head;
			//				for (int i = 0; i < leaf.Count; i++, for_current = for_current.Next)
			//					this._locate(for_current.Value
			//<# for (int k = 1; k <= i; k++) { #>
			//					<#= j == k ? ", out values[i]" : ", out _" #>
			//<# } #>
			//					);
			//				if (_defaultCompare<#= j #>) Array.Sort(values);
			//				else Array.Sort(values, Compare.ToSystemComparison(this._compare<#= j #>));
			//				int index = (leaf.Count - 1) / 2;
			//				division<#= j #> = values[index];
			//			}

			//<# } #>
			//			return new Omnitree.Vector<<#= chain_AxisX #>>(
			//				division1

			//<# for (int j = 2; j <= i; j++) { #>
			//				, division<#= j #>

			//<# } #>
			//				);
			//		}

			//#endregion

			//#region Add Helpers

			//		internal Omnitree.Bounds<<#= chain_AxisX #>> DetermineChildBounds(Branch branch, <#= child_index_type #> child_index)
			//		{

			//<# for (int j = i; j >= 1; j--) { #>
			//			Omnitree.Bound<Axis<#= j #>> min<#= j #>, max<#= j #>;
			//			if (child_index >= <#= (2 << (j - 1)) / 2 #>)
			//			{
			//				min<#= j #> = branch.PointOfDivision.Axis<#= j #>;
			//				max<#= j #> = branch.Bounds.Max<#= j #>;
			//				child_index -= <#= (2 << (j - 1)) / 2 #>;
			//			}
			//			else
			//			{
			//				min<#= j #> = branch.Bounds.Min<#= j #>;
			//				max<#= j #> = branch.PointOfDivision.Axis<#= j #>;
			//			}

			//<# } #>
			//			return new Omnitree.Bounds<<#= chain_AxisX #>>(<#= chain_minX_maxX #>);
			//		}

			//#endregion

			//#endregion

			//#region Clear

			//		/// <summary>Returns the tree to an empty state.</summary>
			//		public void Clear()
			//		{
			//			this._top = new Leaf(Omnitree.Bounds<<#= chain_AxisX #>>.None, null, -1);
			//			Omnitree.ComputeLoads(_top.Count, ref _naturalLogLower, ref _naturalLogUpper, ref _load);
			//		}

			//#endregion

			//#region Clone

			//		/// <summary>Creates a shallow clone of this data structure.</summary>
			//		/// <returns>A shallow clone of this data structure.</returns>
			//		public OmnitreePointsLinked<T, <#= chain_AxisX #>> Clone()
			//		{
			//			return new OmnitreePointsLinked<T, <#= chain_AxisX #>>(this);
			//		}

			//#endregion

			//#region Count

			//		/// <summary>Counts the number of items in a sub space.</summary>
			//		<#= documentation_AxisX_minX_AxisX_maxX #>
			//		/// <returns>The number of items in the provided sub space.</returns>
			//		public int CountSubSpace(<#= chain_AxisX_minX_AxisX_maxX #>)
			//		{
			//			return CountSubSpace(_top, new Omnitree.Bounds<<#= chain_AxisX #>>(<#= chain_minX_maxX #>));
			//		}
			//		/// <summary>Counts the number of items in a sub space.</summary>
			//		<#= documentation_AxisX_minX_AxisX_maxX #>
			//		/// <returns>The number of items in the provided sub space.</returns>
			//		public int CountSubSpace(<#= chain_BoundAxisX_minX_BoundAxisX_maxX #>)
			//		{
			//			return CountSubSpace(_top, new Omnitree.Bounds<<#= chain_AxisX #>>(<#= chain_minX_maxX #>));
			//		}
			//		/// <summary>Counts the number of items in a sub space.</summary>
			//		<#= documentation_AxisX_axisX #>
			//		/// <returns>The number of items in the provided sub space.</returns>
			//		public int CountSubSpace(<#= chain_AxisX_axisX #>)
			//		{
			//			return CountSubSpace(_top, new Omnitree.Bounds<<#= chain_AxisX #>>(<#= chain_axisX_axisX #>));
			//		}
			//		/// <summary>Counts the number of items in a sub space.</summary>
			//		<#= documentation_AxisX_axisX #>
			//		/// <returns>The number of items in the provided sub space.</returns>
			//		public int CountSubSpace(<#= chain_BoundAxisX_axisX #>)
			//		{
			//			return CountSubSpace(_top, new Omnitree.Bounds<<#= chain_AxisX #>>(<#= chain_axisX_axisX #>));
			//		}
			//		/// <summary>Counts the number of items in a sub space.</summary>
			//		/// <param name="node">The current traversal node.</param>
			//		/// <param name="bounds">The bounds of the sub space being counted.</param>
			//		/// <returns>The number of items in the provided sub space.</returns>
			//		internal int CountSubSpace(Node node, Omnitree.Bounds<<#= chain_AxisX #>> bounds)
			//		{
			//			// adjust min/max values
			//			int count = 0;
			//			if (EncapsulationCheck(bounds, node.Bounds))
			//				count += node.Count;
			//			else if (node is Leaf)
			//			{
			//				for (Leaf.Node list = (node as Leaf).Head; !(list is null); list = list.Next)
			//					if (EncapsulationCheck(bounds, LocateVector(list.Value)))
			//						count++;
			//			}
			//			else
			//			{
			//				Branch branch = node as Branch;
			//				if (!StraddlesLines(branch.Bounds, branch.PointOfDivision))
			//				{
			//					<#= child_index_type #> child_index = DetermineChildIndex(branch.PointOfDivision, new Omnitree.Vector<<#= chain_AxisX #>>(bounds.Min1.Value
			//<# for (int j = 2; j <= i; j++) { #>
			//						, bounds.Min<#= j #>.Value
			//<# } #>
			//						));
			//					Node child = branch[child_index];
			//					if (!(child is null))
			//					{
			//						count += this.CountSubSpace(child, bounds);
			//					}
			//				}
			//				else
			//				{
			//					foreach (Node child in (node as Branch).Children)
			//						count += this.CountSubSpace(child, bounds);
			//				}
			//			}
			//			return count;
			//		}

			//#endregion

			//#region Update

			//		/// <summary>Iterates through the entire tree and ensures each item is in the proper leaf.</summary>
			//		public void Update()
			//		{
			//			this.Update(this._top, 0);
			//		}

			//		/// <summary>Recursive version of the Update method.</summary>
			//		/// <param name="node">The current node of iteration.</param>
			//		/// <param name="depth">The current depth of iteration.</param>
			//		internal int Update(Node node, int depth)
			//		{
			//			int removals = 0;

			//			if (node is Leaf)
			//			{
			//				Leaf leaf = node as Leaf;
			//				Leaf.Node current = leaf.Head;
			//				Leaf.Node previous = null;
			//				while (!(current is null))
			//				{
			//					Omnitree.Vector<<#= chain_AxisX #>> location = LocateVector(current.Value);
			//					if (!this.EncapsulationCheck(node.Bounds, location))
			//					{
			//						removals++;
			//						T updated = current.Value;
			//						if (previous is null)
			//						{
			//							leaf.Head = current.Next;
			//							goto HeadRemoved;
			//						}
			//						else
			//							previous.Next = current.Next;

			//						Node whereToAdd = GetEncapsulationParent(node.Parent, location);

			//						if (whereToAdd is null)
			//							throw new System.Exception("an item was updated outside the range of the omnitree");

			//						this.Add(updated, whereToAdd, location, whereToAdd.Depth);
			//					}
			//					previous = current;
			//				HeadRemoved:
			//					current = current.Next;
			//				}
			//				leaf.Count -= removals;
			//				return removals;
			//			}
			//			else
			//			{
			//				Branch branch = node as Branch;
			//				int skipped = 0;
			//				for (int i = 0; i + skipped < branch.Children.Length; )
			//				{
			//					removals += this.Update(branch.Children[i], depth + 1);
			//					if (branch.Children[i].Count == 0)
			//						branch.Children[i] = branch.Children[branch.Children.Length - skipped++ - 1];
			//					else
			//						i++;
			//				}
			//				Node[] newArray = new Node[branch.Children.Length - skipped];
			//				Array.Copy(branch.Children, newArray, newArray.Length);
			//				branch.Children = newArray;

			//				branch.Count -= removals;

			//				if (branch.Count < _load && branch.Count != 0)
			//					ShrinkChild(branch.Parent, branch.Index);
			//			}

			//			return removals;
			//		}

			//		/// <summary>Iterates through the provided dimensions and ensures each item is in the proper leaf.</summary>
			//		<#= documentation_AxisX_minX_AxisX_maxX #>
			//		public void Update(<#= chain_AxisX_minX_AxisX_maxX #>)
			//		{
			//			this.Update(new Omnitree.Bounds<<#= chain_AxisX #>>(<#= chain_minX_maxX #>), this._top, 0);
			//		}
			//		/// <summary>Iterates through the provided dimensions and ensures each item is in the proper leaf.</summary>
			//		<#= documentation_AxisX_minX_AxisX_maxX #>
			//		public void Update(<#= chain_BoundAxisX_minX_BoundAxisX_maxX #>)
			//		{
			//			this.Update(new Omnitree.Bounds<<#= chain_AxisX #>>(<#= chain_minX_maxX #>), this._top, 0);
			//		}
			//		/// <summary>Iterates through the provided dimensions and ensures each item is in the proper leaf.</summary>
			//		<#= documentation_AxisX_axisX #>
			//		public void Update(<#= chain_AxisX_axisX #>)
			//		{
			//			this.Update(new Omnitree.Bounds<<#= chain_AxisX #>>(<#= chain_axisX_axisX #>), this._top, 0);
			//		}
			//		/// <summary>Iterates through the provided dimensions and ensures each item is in the proper leaf.</summary>
			//		<#= documentation_AxisX_axisX #>
			//		public void Update(<#= chain_BoundAxisX_axisX #>)
			//		{
			//			this.Update(new Omnitree.Bounds<<#= chain_AxisX #>>(<#= chain_axisX_axisX #>), this._top, 0);
			//		}
			//		internal int Update(Omnitree.Bounds<<#= chain_AxisX #>> bounds, Node node, int depth)
			//		{
			//			if (!InclusionCheck(bounds, node.Bounds))
			//				return 0;

			//			int removals = 0;

			//			if (node is Leaf)
			//			{
			//				Leaf leaf = node as Leaf;
			//				Leaf.Node current = leaf.Head;
			//				Leaf.Node previous = null;
			//				while (!(current is null))
			//				{
			//					Omnitree.Vector<<#= chain_AxisX #>> location = LocateVector(current.Value);
			//					if (!this.EncapsulationCheck(node.Bounds, location))
			//					{
			//						removals++;
			//						T updated = current.Value;
			//						if (previous is null)
			//						{
			//							leaf.Head = current.Next;
			//							goto HeadRemoved;
			//						}
			//						else
			//							previous.Next = current.Next;
			//						Node whereToAdd = GetEncapsulationParent(node.Parent, location);
			//						if (whereToAdd is null)
			//							throw new System.Exception("an item was updates outside the range of the omnitree");
			//						this.Add(updated, whereToAdd, location, whereToAdd.Depth);
			//					}
			//					previous = current;
			//				HeadRemoved:
			//					current = current.Next;
			//				}
			//				leaf.Count -= removals;
			//				return removals;
			//			}
			//			else
			//			{
			//				Branch branch = node as Branch;
			//				int skipped = 0;
			//				for (int i = 0; i + skipped < branch.Children.Length; )
			//				{
			//					removals += this.Update(branch.Children[i], depth + 1);
			//					if (branch.Children[i].Count == 0)
			//						branch.Children[i] = branch.Children[branch.Children.Length - skipped++ - 1];
			//					else
			//						i++;
			//				}
			//				Node[] newArray = new Node[branch.Children.Length - skipped];
			//				Array.Copy(branch.Children, newArray, newArray.Length);
			//				branch.Children = newArray;

			//				branch.Count -= removals;

			//				if (branch.Count < _load && branch.Count != 0)
			//					ShrinkChild(branch.Parent, branch.Index);
			//			}

			//			return removals;
			//		}

			//#endregion

			//#region Remove

			//		/// <summary>Removes all the items qualified by the delegate.</summary>
			//		/// <param name="where">The predicate to qualify removals.</param>
			//		public void Remove(Predicate<T> where)
			//		{
			//			this.Remove(this._top, where);
			//			Omnitree.ComputeLoads(_top.Count, ref _naturalLogLower, ref _naturalLogUpper, ref _load);
			//		}

			//		/// <summary>Recursive version of the remove method.</summary>
			//		/// <param name="node">The current node of traversal.</param>
			//		/// <param name="where">The predicate to qualify removals.</param>
			//		internal int Remove(Node node, Predicate<T> where)
			//		{
			//			int removals = 0;
			//			if (node is Leaf)
			//			{
			//				Leaf leaf = node as Leaf;
			//				while (!(leaf.Head is null) && where(leaf.Head.Value))
			//				{
			//					leaf.Head = leaf.Head.Next;
			//					removals++;
			//				}
			//				if (!(leaf.Head is null))
			//				{
			//					Leaf.Node list = leaf.Head;
			//					while (!(list.Next is null))
			//					{
			//						if (where(list.Next.Value))
			//						{
			//							list.Next = list.Next.Next;
			//							removals++;
			//						}
			//					}
			//				}

			//				leaf.Count -= removals;
			//				return removals;
			//			}
			//			else
			//			{
			//				Branch branch = node as Branch;
			//				int skipped = 0;
			//				for (int i = 0; i + skipped < branch.Children.Length; )
			//				{
			//					removals += this.Remove(branch.Children[i], where);
			//					if (branch.Children[i].Count == 0)
			//						branch.Children[i] = branch.Children[branch.Children.Length - skipped++ - 1];
			//					else
			//						i++;
			//				}
			//				Node[] newArray = new Node[branch.Children.Length - skipped];
			//				Array.Copy(branch.Children, newArray, newArray.Length);
			//				branch.Children = newArray;

			//				branch.Count -= removals;

			//				if (branch.Count < _load && branch.Count != 0)
			//					ShrinkChild(branch.Parent, branch.Index);

			//				return removals;
			//			}
			//		}

			//		/// <summary>Removes all the items in a given space.</summary>
			//		<#= documentation_AxisX_minX_AxisX_maxX #>
			//		/// <returns>The number of items that were removed.</returns>
			//		public void Remove(<#= chain_AxisX_minX_AxisX_maxX #>)
			//		{
			//			this.Remove(this._top, new Omnitree.Bounds<<#= chain_AxisX #>>(<#= chain_minX_maxX #>));
			//			Omnitree.ComputeLoads(_top.Count, ref _naturalLogLower, ref _naturalLogUpper, ref _load);
			//		}
			//		/// <summary>Removes all the items in a given space.</summary>
			//		<#= documentation_AxisX_minX_AxisX_maxX #>
			//		/// <returns>The number of items that were removed.</returns>
			//		public void Remove(<#= chain_BoundAxisX_minX_BoundAxisX_maxX #>)
			//		{
			//			this.Remove(this._top, new Omnitree.Bounds<<#= chain_AxisX #>>(<#= chain_minX_maxX #>));
			//			Omnitree.ComputeLoads(_top.Count, ref _naturalLogLower, ref _naturalLogUpper, ref _load);
			//		}
			//		internal int Remove(Node node, Omnitree.Bounds<<#= chain_AxisX #>> bounds)
			//		{
			//			int removals = 0;
			//			if (InclusionCheck(bounds, node.Bounds))
			//			{
			//				if (node is Leaf)
			//				{
			//					Leaf leaf = node as Leaf;
			//					Leaf.Node current_node = leaf.Head;
			//					Leaf.Node previous_node = null;
			//					while (!(current_node is null))
			//					{
			//						Leaf.Node temp_previous = current_node;
			//						if (EncapsulationCheck(bounds, LocateVector(current_node.Value)))
			//						{
			//							removals++;
			//							if (current_node == leaf.Head)
			//								leaf.Head = leaf.Head.Next;
			//							else
			//							{
			//								previous_node.Next = current_node.Next;
			//								temp_previous = previous_node;
			//							}
			//						}
			//						previous_node = temp_previous;
			//						current_node = current_node.Next;
			//					}
			//					leaf.Count -= removals;
			//				}
			//				else
			//				{
			//					Branch branch = node as Branch;
			//					int skipped = 0;
			//					for (int i = 0; i + skipped < branch.Children.Length; )
			//					{
			//						removals += this.Remove(branch.Children[i], bounds);
			//						if (branch.Children[i].Count == 0)
			//							branch.Children[i] = branch.Children[branch.Children.Length - skipped++ - 1];
			//						else
			//							i++;
			//					}
			//					Node[] newArray = new Node[branch.Children.Length - skipped];
			//					Array.Copy(branch.Children, newArray, newArray.Length);
			//					branch.Children = newArray;

			//					branch.Count -= removals;
			//					// convert this branch back into a leaf
			//					// Note: if count is zero, it will be chopped off
			//					if (branch.Count < _load && branch.Count > 0)
			//						ShrinkChild(branch.Parent, branch.Index);
			//				}
			//			}

			//			return removals;
			//		}

			//		/// <summary>Removes all the items in a given space validated by a predicate.</summary>
			//		<#= documentation_AxisX_minX_AxisX_maxX #>
			//		/// <param name="where">The equality constraint of the removal.</param>
			//		public void Remove(<#= chain_AxisX_minX_AxisX_maxX #>, Predicate<T> where)
			//		{
			//			this.Remove(this._top, new Omnitree.Bounds<<#= chain_AxisX #>>(<#= chain_minX_maxX #>), where);
			//			Omnitree.ComputeLoads(_top.Count, ref _naturalLogLower, ref _naturalLogUpper, ref _load);
			//		}
			//		/// <summary>Removes all the items in a given space validated by a predicate.</summary>
			//		<#= documentation_AxisX_minX_AxisX_maxX #>
			//		/// <param name="where">The equality constraint of the removal.</param>
			//		public void Remove(<#= chain_BoundAxisX_minX_BoundAxisX_maxX #>, Predicate<T> where)
			//		{
			//			this.Remove(this._top, new Omnitree.Bounds<<#= chain_AxisX #>>(<#= chain_minX_maxX #>), where);
			//			Omnitree.ComputeLoads(_top.Count, ref _naturalLogLower, ref _naturalLogUpper, ref _load);
			//		}
			//		internal int Remove(Node node, Omnitree.Bounds<<#= chain_AxisX #>> bounds, Predicate<T> where)
			//		{
			//			if (!InclusionCheck(node.Bounds, bounds))
			//				return 0;
			//			int removals = 0;
			//			if (node is Leaf)
			//			{
			//				Leaf leaf = node as Leaf;
			//				Leaf.Node current = leaf.Head;
			//				Leaf.Node previous = null;
			//				while (!(current is null))
			//				{
			//					if (this.EncapsulationCheck(bounds, LocateVector(current.Value)) && where(current.Value))
			//					{
			//						removals++;
			//						if (previous is null)
			//						{
			//							leaf.Head = current.Next;
			//							goto HeadRemoved;
			//						}
			//						else
			//							previous.Next = current.Next;
			//					}
			//					previous = current;
			//				HeadRemoved:
			//					current = current.Next;
			//				}

			//				leaf.Count -= removals;
			//				return removals;
			//			}
			//			else
			//			{
			//				Branch branch = node as Branch;
			//				int skipped = 0;
			//				for (int i = 0; i + skipped < branch.Children.Length; )
			//				{
			//					removals += this.Remove(branch.Children[i], bounds, where);
			//					if (branch.Children[i].Count == 0)
			//						branch.Children[i] = branch.Children[branch.Children.Length - skipped++ - 1];
			//					else
			//						i++;
			//				}
			//				Node[] newArray = new Node[branch.Children.Length - skipped];
			//				Array.Copy(branch.Children, newArray, newArray.Length);
			//				branch.Children = newArray;

			//				node.Count -= removals;

			//				if (node.Count < _load && node.Count != 0)
			//					ShrinkChild(node.Parent, node.Index);

			//				return removals;
			//			}
			//		}

			//		/// <summary>Tries to remove a value.</summary>
			//		/// <param name="value">The value to remove.</param>
			//		/// <param name="exception">The exception that occurred if the remove failed.</param>
			//		/// <returns>True if successful or false if not.</returns>
			//		public bool TryRemove(T value, out Exception exception)
			//		{
			//			Remove(value);
			//			exception = null;
			//			return true;
			//		}

			//		/// <summary>Removes all instances of a given value.</summary>
			//		public void Remove(T removal) => Omnitree.Remove(this, removal);

			//		/// <summary>Removes all instances of a given value.</summary>
			//		public void Remove(T removal, Func<T, T, bool> equate) => Omnitree.Remove(this, removal, equate);

			//		/// <summary>Removes all the items in a given space.</summary>
			//		<#= documentation_axisX #>
			//		/// <returns>The number of items that were removed.</returns>
			//		public void Remove(Axis1 axis1
			//<# for (int j = 2; j <= i; j++) { #>
			//			, Axis<#= j #> axis<#= j #>
			//<# } #>
			//			)
			//		{
			//			this.Remove(this._top, new Omnitree.Vector<<#= chain_AxisX #>>(axis1
			//<# for (int j = 2; j <= i; j++) { #>
			//				, axis<#= j #>
			//<# } #>
			//				));
			//			Omnitree.ComputeLoads(_top.Count, ref _naturalLogLower, ref _naturalLogUpper, ref _load);
			//		}
			//		internal int Remove(Node node, Omnitree.Vector<<#= chain_AxisX #>> vector)
			//		{
			//			int removals = 0;
			//			if (node is Leaf)
			//			{
			//				Leaf leaf = node as Leaf;
			//				Leaf.Node current_node = leaf.Head;
			//				Leaf.Node previous_node = null;
			//				while (!(current_node is null))
			//				{
			//					Leaf.Node temp_previous = current_node;
			//					if (EqualsCheck(vector, LocateVector(current_node.Value)))
			//					{
			//						removals++;
			//						if (current_node == leaf.Head)
			//							leaf.Head = leaf.Head.Next;
			//						else
			//						{
			//							previous_node.Next = current_node.Next;
			//							temp_previous = previous_node;
			//						}
			//					}
			//					previous_node = temp_previous;
			//					current_node = current_node.Next;
			//				}
			//				leaf.Count -= removals;
			//			}
			//			else
			//			{
			//				Branch branch = node as Branch;
			//				<#= child_index_type #> child_index = DetermineChildIndex(branch.PointOfDivision, vector);
			//				removals += Remove(branch[child_index], vector);
			//				branch.Count -= removals;
			//				// convert this branch back into a leaf
			//				// Note: if count is zero, it will be chopped off
			//				if (branch.Count < _load && branch.Count > 0)
			//					ShrinkChild(branch.Parent, branch.Index);
			//			}

			//			return removals;
			//		}

			//		/// <summary>Removes all the items in a given space validated by a predicate.</summary>
			//		<#= documentation_axisX #>
			//		/// <param name="where">The equality constraint of the removal.</param>
			//		public void Remove(<#= chain_AxisX_axisX #>, Predicate<T> where)
			//		{
			//			this.Remove(this._top, new Omnitree.Vector<<#= chain_AxisX #>>(<#= chain_axisX #>), where);
			//			Omnitree.ComputeLoads(_top.Count, ref _naturalLogLower, ref _naturalLogUpper, ref _load);
			//		}
			//		internal int Remove(Node node, Omnitree.Vector<<#= chain_AxisX #>> vector, Predicate<T> where)
			//		{
			//			int removals = 0;
			//			if (node is Leaf)
			//			{
			//				Leaf leaf = node as Leaf;
			//				Leaf.Node current_node = leaf.Head;
			//				Leaf.Node previous_node = null;
			//				while (!(current_node is null))
			//				{
			//					Leaf.Node temp_previous = current_node;
			//					if (EqualsCheck(vector, LocateVector(current_node.Value)) && where(current_node.Value))
			//					{
			//						removals++;
			//						if (current_node == leaf.Head)
			//							leaf.Head = leaf.Head.Next;
			//						else
			//						{
			//							previous_node.Next = current_node.Next;
			//							temp_previous = previous_node;
			//						}
			//					}
			//					previous_node = temp_previous;
			//					current_node = current_node.Next;
			//				}
			//				leaf.Count -= removals;
			//			}
			//			else
			//			{
			//				Branch branch = node as Branch;
			//				<#= child_index_type #> child_index = DetermineChildIndex(branch.PointOfDivision, vector);
			//				removals += Remove(branch[child_index], vector, where);
			//				branch.Count -= removals;
			//				// convert this branch back into a leaf
			//				// Note: if count is zero, it will be chopped off
			//				if (branch.Count < _load && branch.Count > 0)
			//					ShrinkChild(branch.Parent, branch.Index);
			//			}
			//			return removals;
			//		}

			//#endregion

			//#region Stepper And IEnumerable

			//		/// <summary>Traverses every item in the tree and performs the delegate in them.</summary>
			//		/// <param name="step">The delegate to perform on every item in the tree.</param>
			//		public void Stepper(Action<T> step) =>
			//			this.Stepper(step, this._top);

			//		internal void Stepper(Action<T> step, Node node)
			//		{
			//			if (node is Leaf)
			//			{
			//				Leaf.Node list = (node as Leaf).Head;
			//				while (!(list is null))
			//				{
			//					step(list.Value);
			//					list = list.Next;
			//				}
			//			}
			//			else
			//			{
			//				foreach (Node child in (node as Branch).Children)
			//					this.Stepper(step, child);
			//			}
			//		}

			//		/// <summary>Traverses every item in the tree and performs the delegate in them.</summary>
			//		/// <param name="step">The delegate to perform on every item in the tree.</param>
			//		public StepStatus Stepper(Func<T, StepStatus> step) =>
			//			Stepper(step, _top);

			//		internal StepStatus Stepper(Func<T, StepStatus> step, Node node)
			//		{
			//			StepStatus status = StepStatus.Continue;
			//			if (node is Leaf)
			//			{
			//				for (Leaf.Node list = (node as Leaf).Head; !(list is null); list = list.Next)
			//					if ((status = step(list.Value)) != StepStatus.Continue)
			//						break;
			//			}
			//			else
			//			{
			//				foreach (Node child in (node as Branch).Children)
			//					if ((status = Stepper(step, child)) != StepStatus.Continue)
			//						break;
			//			}
			//			return status;
			//		}

			//		/// <summary>Performs and specialized traversal of the structure and performs a delegate on every node within the provided dimensions.</summary>
			//		/// <param name="step">The delegate to perform on all items in the tree within the given bounds.</param>
			//		<#= documentation_AxisX_minX_AxisX_maxX #>
			//		public void Stepper(Action<T> step, <#= chain_AxisX_minX_AxisX_maxX #>) =>
			//			Stepper(step, _top, new Omnitree.Bounds<<#= chain_AxisX #>>(<#= chain_minX_maxX #>));

			//		/// <summary>Performs and specialized traversal of the structure and performs a delegate on every node within the provided dimensions.</summary>
			//		/// <param name="step">The delegate to perform on all items in the tree within the given bounds.</param>
			//		<#= documentation_AxisX_minX_AxisX_maxX #>
			//		public void Stepper(Action<T> step, <#= chain_BoundAxisX_minX_BoundAxisX_maxX #>) =>
			//			Stepper(step, _top, new Omnitree.Bounds<<#= chain_AxisX #>>(<#= chain_minX_maxX #>));

			//		internal void Stepper(Action<T> step, Node node, Omnitree.Bounds<<#= chain_AxisX #>> bounds)
			//		{
			//			if (node is Leaf)
			//			{
			//				for (Leaf.Node list = (node as Leaf).Head; !(list is null); list = list.Next)
			//					if (EncapsulationCheck(bounds, LocateVector(list.Value)))
			//						step(list.Value);
			//			}
			//			else
			//			{
			//				foreach (Node child in (node as Branch).Children)
			//					// optimization: stop bounds checking if space encapsulates node
			//					if (EncapsulationCheck(bounds, child.Bounds))
			//						this.Stepper(step, child);
			//					else if (InclusionCheck(child.Bounds, bounds))
			//						this.Stepper(step, child, bounds);
			//			}
			//		}

			//		/// <summary>Performs and specialized traversal of the structure and performs a delegate on every node within the provided dimensions.</summary>
			//		/// <param name="step">The delegate to perform on all items in the tree within the given bounds.</param>
			//		<#= documentation_AxisX_minX_AxisX_maxX #>
			//		public StepStatus Stepper(Func<T, StepStatus> step, <#= chain_AxisX_minX_AxisX_maxX #>) =>
			//			Stepper(step, _top, new Omnitree.Bounds<<#= chain_AxisX #>>(<#= chain_minX_maxX #>));

			//		/// <summary>Performs and specialized traversal of the structure and performs a delegate on every node within the provided dimensions.</summary>
			//		/// <param name="step">The delegate to perform on all items in the tree within the given bounds.</param>
			//		<#= documentation_AxisX_minX_AxisX_maxX #>
			//		public StepStatus Stepper(Func<T, StepStatus> step, <#= chain_BoundAxisX_minX_BoundAxisX_maxX #>) =>
			//			Stepper(step, _top, new Omnitree.Bounds<<#= chain_AxisX #>>(<#= chain_minX_maxX #>));

			//		internal StepStatus Stepper(Func<T, StepStatus> step, Node node, Omnitree.Bounds<<#= chain_AxisX #>> bounds)
			//		{
			//			StepStatus status = StepStatus.Continue;
			//			if (node is Leaf)
			//			{
			//				for (Leaf.Node list = (node as Leaf).Head; !(list is null); list = list.Next)
			//					if (EncapsulationCheck(bounds, LocateVector(list.Value)) &&
			//						(status = step(list.Value)) != StepStatus.Continue)
			//						break;
			//			}
			//			else
			//			{
			//				foreach (Node child in (node as Branch).Children)
			//					// optimization: stop bounds checking if space encapsulates node
			//					if (EncapsulationCheck(bounds, child.Bounds) &&
			//						(status = this.Stepper(step, child)) != StepStatus.Continue)
			//						break;
			//					else if (!InclusionCheck(child.Bounds, bounds) &&
			//						(status = this.Stepper(step, child, bounds)) != StepStatus.Continue)
			//						break;
			//			}
			//			return status;
			//		}

			//		/// <summary>Performs and specialized traversal of the structure and performs a delegate on every node within the provided dimensions.</summary>
			//		/// <param name="step">The delegate to perform on all items in the tree within the given bounds.</param>
			//		<#= documentation_axisX #>
			//		public void Stepper(Action<T> step, <#= chain_AxisX_axisX #>) =>
			//			Stepper(step, _top, new Omnitree.Vector<<#= chain_AxisX #>>(<#= chain_axisX #>));

			//		internal void Stepper(Action<T> step, Node node, Omnitree.Vector<<#= chain_AxisX #>> vector)
			//		{
			//			Node current = node;
			//			while (!(current is null))
			//			{
			//				if (current is Leaf)
			//				{
			//					for (Leaf.Node leaf_node = (current as Leaf).Head; !(leaf_node is null); leaf_node = leaf_node.Next)
			//						if (EqualsCheck(vector, LocateVector(leaf_node.Value)))
			//							step(leaf_node.Value);
			//					break;
			//				}
			//				else
			//				{
			//					Branch branch = current as Branch;
			//					<#= child_index_type #> child_index = DetermineChildIndex(branch.PointOfDivision, vector);
			//					current = branch[child_index];
			//				}
			//			}
			//		}

			//		/// <summary>Performs and specialized traversal of the structure and performs a delegate on every node within the provided dimensions.</summary>
			//		/// <param name="step">The delegate to perform on all items in the tree within the given bounds.</param>
			//		<#= documentation_axisX #>
			//		public StepStatus Stepper(Func<T, StepStatus> step, <#= chain_AxisX_axisX #>) =>
			//			Stepper(step, _top, new Omnitree.Vector<<#= chain_AxisX #>>(<#= chain_axisX #>));

			//		internal StepStatus Stepper(Func<T, StepStatus> step, Node node, Omnitree.Vector<<#= chain_AxisX #>> vector)
			//		{
			//			Node current = node;
			//			while (!(current is null))
			//			{
			//				if (current is Leaf)
			//				{
			//					for (Leaf.Node list = (current as Leaf).Head; !(list is null); list = list.Next)
			//					{
			//						StepStatus status = StepStatus.Continue;
			//						if (EqualsCheck(vector, LocateVector(list.Value)) &&
			//							(status = step(list.Value)) != StepStatus.Continue)
			//							return status;
			//					}
			//				}
			//				else
			//				{
			//					Branch branch = current as Branch;
			//					<#= child_index_type #> child_index = DetermineChildIndex(branch.PointOfDivision, vector);
			//					current = branch[child_index];
			//				}
			//			}
			//			return StepStatus.Continue;
			//		}

			//		System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() => GetEnumerator();

			//		public System.Collections.Generic.IEnumerator<T> GetEnumerator()
			//		{
			//			// Note: this can be optimized.
			//			IList<T> list = new ListLinked<T>();
			//			Stepper(x => list.Add(x));
			//			return list.GetEnumerator();
			//		}

			//#endregion

			//#region Helpers

			//		internal bool StraddlesLines(Omnitree.Bounds<<#= chain_AxisX #>> bounds, Omnitree.Vector<<#= chain_AxisX #>> vector) =>
			//			Omnitree.StraddlesLines(bounds, vector
			//<# for (int j = 1; j <= i; j++) { #>
			//				, _compare<#= j #>
			//<# } #>
			//				);

			//		/// <summary>Computes the child index that contains the desired dimensions.</summary>
			//		/// <param name="pointOfDivision">The point of division to compare against.</param>
			//		/// <param name="vector">The dimensions to determine the child index.</param>
			//		/// <returns>The computed child index based on the coordinates relative to the center of the node.</returns>
			//		internal <#= child_index_type #> DetermineChildIndex(Omnitree.Vector<<#= chain_AxisX #>> pointOfDivision, Omnitree.Vector<<#= chain_AxisX #>> vector)
			//		{
			//			<#= child_index_type #> child = 0;
			//<# for (int j = 1; j <= i; j++) { #>
			//			if (!(this._compare<#= j #>(vector.Axis<#= j #>, pointOfDivision.Axis<#= j #>) == CompareResult.Less))
			//				child += 1 << <#= j - 1 #>;
			//<# } #>
			//			return child;
			//		}

			//		/// <summary>Converts a branch back into a leaf when the count is reduced.</summary>
			//		/// <param name="parent">The parent to shrink a child of.</param>
			//		/// <param name="child_index">The index of the child to shrink.</param>
			//		internal void ShrinkChild(Branch parent, <#= child_index_type #> child_index)
			//		{
			//			Leaf leaf;
			//			Node removal = null;
			//			if (parent is null) // top of tree
			//			{
			//				removal = this._top;
			//				leaf = new Leaf(Omnitree.Bounds<<#= chain_AxisX #>>.None, null, -1);
			//				this._top = leaf;
			//			}
			//			else // non-top branch
			//			{
			//				removal = parent[child_index];
			//				leaf = new Leaf(removal.Bounds, removal.Parent, removal.Index);
			//				parent[child_index] = leaf;
			//			}

			//			this.Stepper((T step) => { leaf.Add(step); }, removal);
			//		}

			//		/// <summary>Reduces the counts of all the parents of a given node by a given amount.</summary>
			//		/// <param name="parent">The starting parent of the reduction.</param>
			//		/// <param name="reduction">The amount to reduce the parent counts by.</param>
			//		internal void ReduceParentCounts(Node parent, int reduction)
			//		{
			//			IncreaseParentCounts(parent, -reduction);
			//		}

			//		/// <summary>Increases the counts of all the parents of a given node by a given amount.</summary>
			//		/// <param name="parent">The starting parent of the increase.</param>
			//		/// <param name="increase">The amount to increase the parent counts by.</param>
			//		internal void IncreaseParentCounts(Node parent, int increase)
			//		{
			//			Node node = parent;
			//			while (!(node is null))
			//			{
			//				node.Count += increase;
			//				node = node.Parent;
			//			}
			//		}

			//		/// <summary>Checks a node for inclusion (overlap) between two bounds.</summary>
			//		/// <returns>True if the spaces overlap; False if not.</returns>
			//		internal bool InclusionCheck(Omnitree.Bounds<<#= chain_AxisX #>> a, Omnitree.Bounds<<#= chain_AxisX #>> b) =>
			//			Omnitree.InclusionCheck(a, b
			//<# for (int j = 1; j <= i; j++) { #>
			//			, _compare<#= j #>
			//<# } #>
			//			);

			//		/// <summary>Checks if a space encapsulates a point.</summary>
			//		/// <returns>True if the space encapsulates the point; False if not.</returns>
			//		internal bool EncapsulationCheck(Omnitree.Bounds<<#= chain_AxisX #>> bounds, Omnitree.Vector<<#= chain_AxisX #>> vector) =>
			//			Omnitree.EncapsulationCheck(bounds, vector
			//<# for (int j = 1; j <= i; j++) { #>
			//			, _compare<#= j #>
			//<# } #>
			//			);

			//		/// <summary>Checks if a space (left) encapsulates another space (right).</summary>
			//		/// <returns>True if the left space encapsulates the right; False if not.</returns>
			//		internal bool EncapsulationCheck(Omnitree.Bounds<<#= chain_AxisX #>> a, Omnitree.Bounds<<#= chain_AxisX #>> b) =>
			//			Omnitree.EncapsulationCheck(a, b
			//<# for (int j = 1; j <= i; j++) { #>
			//			, _compare<#= j #>
			//<# } #>
			//			);

			//		/// <summary>Checks for equality between two locations.</summary>
			//		/// <returns>True if equal; False if not;</returns>
			//		internal bool EqualsCheck(Omnitree.Vector<<#= chain_AxisX #>> a, Omnitree.Vector<<#= chain_AxisX #>> b) =>
			//			Omnitree.EqualsCheck(a, b
			//<# for (int j = 1; j <= i; j++) { #>
			//			, Equate.FromCompare(_compare<#= j #>)
			//<# } #>
			//			);

			//		/// <summary>Gets the nearest parent that encapsulates a location.</summary>
			//		/// <param name="node">The starting node to find the encapsulating parent of the location.</param>
			//		/// <param name="vector">The coordinates of the value.</param>
			//		/// <returns>The nearest node that encapsulates the given location.</returns>
			//		internal Node GetEncapsulationParent(Node node, Omnitree.Vector<<#= chain_AxisX #>> vector)
			//		{
			//			while (!(node is null) && !EncapsulationCheck(node.Bounds, vector))
			//			{
			//				node = node.Parent;
			//			}
			//			return node;
			//		}

			//		internal Omnitree.Vector<<#= chain_AxisX #>> LocateVector(T value)
			//		{
			//<# for (int j = 1; j <= i; j++) { #>
			//			Axis<#= j #> axis<#= j #>;
			//<# } #>
			//			this._locate(value, out axis1
			//<# for (int j = 2; j <= i; j++) { #>, out axis<#= j #>
			//<# } #>);
			//			return new Omnitree.Vector<<#= chain_AxisX #>>(<#= chain_axisX #>);
			//		}

			//#endregion

			//#endregion
			//	}

			//#endregion
			//<# } #>

			//#endregion

			//#region OmnitreeBounds
			//<# foreach (int i in dimensionsToGenerate) {
			//// ------------------------------------------------------------------------------------------------------------------------------ 
			//	// PARAMETER/ARGUMENT CHAINS
			//	string chain_AxisX = "Axis1"; for (int j = 2; j <= i; j++) { chain_AxisX += ", Axis" + j; } 
			//	string chain_axisX = "axis1"; for (int j = 2; j <= i; j++) { chain_axisX += ", axis" + j; } 
			//	string chain_AxisX_axisX = "Axis1 axis1"; for (int j = 2; j <= i; j++) { chain_AxisX_axisX += ", Axis" + j + " axis" + j; }
			//	string chain_AxisX_minX_AxisX_maxX = "Axis1 min1, Axis1 max1"; for (int j = 2; j <= i; j++) { chain_AxisX_minX_AxisX_maxX += ", Axis" + j + " min" + j + ", Axis" + j + " max" + j; }
			//	string chain_BoundAxisX_minX_BoundAxisX_maxX = "Omnitree.Bound<Axis1> min1, Omnitree.Bound<Axis1> max1"; for (int j = 2; j <= i; j++) { chain_BoundAxisX_minX_BoundAxisX_maxX += ", Omnitree.Bound<Axis" + j + "> min" + j + ", Omnitree.Bound<Axis" + j + "> max" + j; }
			//	string chain_BoundAxisX_axisX = "Omnitree.Bound<Axis1> axis1"; for (int j = 2; j <= i; j++) { chain_BoundAxisX_axisX += ", Omnitree.Bound<Axis" + j + "> axis" + j; }
			//	string chain_minX_maxX = "min1, max1"; for (int j = 2; j <= i; j++) { chain_minX_maxX += ", min" + j + ", max" + j; }
			//	string chain_axisX_axisX = "axis1, axis1"; for (int j = 2; j <= i; j++) { chain_axisX_axisX += ", axis" + j + ", axis" + j; }
			//	string child_index_type; if (i <= 30) { child_index_type = "int"; } else if (i <= 60) { child_index_type = "long"; } else { child_index_type = "BigInteger"; }
			//	// DOCUMENTATION
			//	string documentation_AxisX_axisX = string.Empty; for (int j = 1; j <= i; j++) { documentation_AxisX_axisX += "\n\t\t/// <param name=\"axis" + j + "\">The coordinate along the " + j + "D axis.</param>"; } documentation_AxisX_axisX = documentation_AxisX_axisX.Trim();
			//	string documentation_AxisX_minX_AxisX_maxX = string.Empty; for (int j = 1; j <= i; j++) { documentation_AxisX_minX_AxisX_maxX += "\n\t\t/// <param name=\"min" + j + "\">The minimum coordinate of the space along the " + j + " axis.</param>\n\t\t/// <param name=\"max" + j + "\">The maximum coordinate of the space along the " + j + " axis.</param>"; } documentation_AxisX_minX_AxisX_maxX = documentation_AxisX_minX_AxisX_maxX.Trim();
			//	string documentation_axisX = string.Empty; for (int j = 1; j <= i; j++) { documentation_axisX += "\n\t\t/// <param name=\"axis" + j + "\">The axis of the removal along the  " + j + "D axis.</param>"; } documentation_axisX = documentation_axisX.Trim();
			// // ------------------------------------------------------------------------------------------------------------------------------ #>

			//#region <#= i #> Dimensional

			//	/// <summary>Inheritance base for <#= i #>D omnitrees that store bounds.</summary>
			//	/// <typeparam name="T">The type of items to store in the omnitree.</typeparam>
			//<# for (int j = 1; j <= i; j++) { #>
			//	/// <typeparam name="Axis<#= j #>">The type <#= j #>D axis.</typeparam>
			//<# } #>
			//	public interface IOmnitreeBounds<T, <#= chain_AxisX #>> : IOmnitree<T, <#= chain_AxisX #>>
			//	{
			//#region Properties

			//		/// <summary>The number of dimensions in this tree.</summary>
			//		int Dimensions { get; }

			//		/// <summary>The delegate being used by the omnitree to get the bounds of values in <#= i #>D space.</summary>
			//		Omnitree.GetBounds<T, Axis1
			//<# for (int j = 2; j <= i; j++) { #>, Axis<#= j #>
			//<# } #>
			//			> GetBounds { get; }

			//#endregion

			//#region Methods

			//		/// <summary>Counts the number of items encapsulated by a sub space.</summary>
			//		<#= documentation_AxisX_minX_AxisX_maxX #>
			//		/// <returns>The number of items in the provided sub space.</returns>
			//		int CountSubSpaceEncapsulated(<#= chain_AxisX_minX_AxisX_maxX #>);

			//		/// <summary>Counts the number of items overlapped by a sub space.</summary>
			//		<#= documentation_AxisX_minX_AxisX_maxX #>
			//		/// <returns>The number of items in the provided sub space.</returns>
			//		int CountSubSpaceOverlapped(<#= chain_AxisX_minX_AxisX_maxX #>);

			//		/// <summary>Iterates through the entire tree and ensures each item is in the proper leaf.</summary>
			//		void Update();
			//		/// <summary>Iterates through the provided dimensions and ensures each item is in the proper leaf.</summary>
			//		<#= documentation_AxisX_minX_AxisX_maxX #>
			//		void Update(<#= chain_AxisX_minX_AxisX_maxX #>);

			//		/// <summary>Removes all the items in a given space.</summary>
			//		<#= documentation_AxisX_minX_AxisX_maxX #>
			//		void RemoveEncapsulated(<#= chain_AxisX_minX_AxisX_maxX #>);
			//		/// <summary>Removes all the items in a given space.</summary>
			//		<#= documentation_AxisX_minX_AxisX_maxX #>
			//		void RemoveEncapsulated(<#= chain_BoundAxisX_minX_BoundAxisX_maxX #>);
			//		/// <summary>Removes all the items in a given space where predicate is met.</summary>
			//		<#= documentation_AxisX_minX_AxisX_maxX #>
			//		/// <param name="where">The predicate constraint of the removal.</param>
			//		void RemoveEncapsulated(<#= chain_AxisX_minX_AxisX_maxX #>, Predicate<T> where);
			//		/// <summary>Removes all the items in a given space where predicate is met.</summary>
			//		<#= documentation_AxisX_minX_AxisX_maxX #>
			//		/// <param name="where">The predicate constraint of the removal.</param>
			//		void RemoveEncapsulated(<#= chain_BoundAxisX_minX_BoundAxisX_maxX #>, Predicate<T> where);

			//		/// <summary>Removes all the items in a given space.</summary>
			//		<#= documentation_AxisX_axisX #>
			//		void RemoveOverlapped(<#= chain_AxisX_axisX #>);
			//		/// <summary>Removes all the items in a given space.</summary>
			//		<#= documentation_AxisX_minX_AxisX_maxX #>
			//		void RemoveOverlapped(<#= chain_AxisX_minX_AxisX_maxX #>);
			//		/// <summary>Removes all the items in a given space.</summary>
			//		<#= documentation_AxisX_minX_AxisX_maxX #>
			//		void RemoveOverlapped(<#= chain_BoundAxisX_minX_BoundAxisX_maxX #>);
			//		/// <summary>Removes all the items in a given space where equality is met.</summary>
			//		<#= documentation_AxisX_axisX #>
			//		/// <param name="where">The equality constraint of the removal.</param>
			//		void RemoveOverlapped(<#= chain_AxisX_axisX #>, Predicate<T> where);
			//		/// <summary>Removes all the items in a given space where predicate is met.</summary>
			//		<#= documentation_AxisX_minX_AxisX_maxX #>
			//		/// <param name="where">The predicate constraint of the removal.</param>
			//		void RemoveOverlapped(<#= chain_AxisX_minX_AxisX_maxX #>, Predicate<T> where);
			//		/// <summary>Removes all the items in a given space where predicate is met.</summary>
			//		<#= documentation_AxisX_minX_AxisX_maxX #>
			//		/// <param name="where">The predicate constraint of the removal.</param>
			//		void RemoveOverlapped(<#= chain_BoundAxisX_minX_BoundAxisX_maxX #>, Predicate<T> where);

			//		/// <summary>Performs and specialized traversal of the structure and performs a delegate on every node within the provided dimensions.</summary>
			//		/// <param name="step">The step function to perform on all items in the tree within the given bounds.</param>
			//		<#= documentation_AxisX_minX_AxisX_maxX #>
			//		void StepperEncapsulated(Action<T> step, <#= chain_BoundAxisX_minX_BoundAxisX_maxX #>);
			//		/// <summary>Performs and specialized traversal of the structure and performs a delegate on every node within the provided dimensions.</summary>
			//		/// <param name="step">The step function to perform on all items in the tree within the given bounds.</param>
			//		<#= documentation_AxisX_minX_AxisX_maxX #>
			//		StepStatus StepperEncapsulated(Func<T, StepStatus> step, <#= chain_BoundAxisX_minX_BoundAxisX_maxX #>);

			//		/// <summary>Performs and specialized traversal of the structure and performs a delegate on every node within the provided dimensions.</summary>
			//		/// <param name="step">The step function to perform on all items in the tree within the given bounds.</param>
			//		<#= documentation_AxisX_minX_AxisX_maxX #>
			//		void StepperOverlapped(Action<T> step, <#= chain_BoundAxisX_minX_BoundAxisX_maxX #>);
			//		/// <summary>Performs and specialized traversal of the structure and performs a delegate on every node within the provided dimensions.</summary>
			//		/// <param name="step">The step function to perform on all items in the tree within the given bounds.</param>
			//		<#= documentation_AxisX_minX_AxisX_maxX #>
			//		StepStatus StepperOverlapped(Func<T, StepStatus> step, <#= chain_BoundAxisX_minX_BoundAxisX_maxX #>);

			//		/// <summary>Performs and specialized traversal of the structure and performs a delegate on every node within the provided dimensions.</summary>
			//		/// <param name="step">The step function to perform on all items in the tree within the given bounds.</param>
			//		<#= documentation_AxisX_axisX #>
			//		void StepperOverlapped(Action<T> step, <#= chain_AxisX_axisX #>);
			//		/// <summary>Performs and specialized traversal of the structure and performs a delegate on every node within the provided dimensions.</summary>
			//		/// <param name="step">The step function to perform on all items in the tree within the given bounds.</param>
			//		<#= documentation_AxisX_axisX #>
			//		StepStatus StepperOverlapped(Func<T, StepStatus> step, <#= chain_AxisX_axisX #>);

			//#endregion
			//	}

			//	/// <summary>Omnitree that stores bounds along <#= i #> dimensions implemented as a linked tree.</summary>
			//	/// <typeparam name="T">The type of items to store in the omnitree.</typeparam>
			//<# for (int j = 1; j <= i; j++) { #>
			//	/// <typeparam name="Axis<#= j #>">The type <#= j #>D axis.</typeparam>
			//<# } #>
			//	public class OmnitreeBoundsLinked<T, <#= chain_AxisX #>> : IOmnitreeBounds<T, <#= chain_AxisX #>>
			//	{
			//		internal const int _dimensions = <#= i #>;
			//		internal static <#= child_index_type #> _children_per_node = (<#= child_index_type #>)BigInteger.Pow(2, <#= i #>);

			//		internal Node _top;
			//		internal int _naturalLogLower = 1; // caching the next time to calculate loads (lower count)
			//		internal int _naturalLogUpper = -1; // caching the next time to calculate loads (upper count)
			//		internal int _load; // ln(count); min = _defaultLoad
			//		internal Omnitree.GetBounds<T, Axis1
			//<# for (int j = 2; j <= i; j++) { #>, Axis<#= j #>
			//<# } #>
			//			> _getBounds;
			//<# for (int j = 1; j <= i; j++) { #>
			//		internal bool _defaultCompare<#= j #>;
			//		internal Compare<Axis<#= j #>> _compare<#= j #>;
			//<# } #>
			//<# for (int j = 1; j <= i; j++) { #>
			//		internal Omnitree.SubdivisionOverride<T, Axis<#= j #>, Omnitree.Bounds<<#= chain_AxisX #>>> _subdivisionOverride<#= j #>;
			//<# } #>

			//#region Nested Types

			//		/// <summary>Can be a leaf or a branch.</summary>
			//		internal class Node
			//		{
			//			internal class ValueNode
			//			{
			//				internal T Value;
			//				internal ValueNode Next;

			//				internal ValueNode(T value, ValueNode next)
			//				{
			//					Value = value;
			//					Next = next;
			//				}
			//			}

			//			internal Omnitree.Bounds<<#= chain_AxisX #>> Bounds;
			//			internal Node Parent;
			//			internal <#= child_index_type #> Index;
			//			internal int Count;
			//			internal ValueNode Head;
			//			internal Node[] Children;
			//			internal Omnitree.Vector<<#= chain_AxisX #>>? PointOfDivision;

			//			/// <summary>Gets child by index.</summary>
			//			/// <param name="child_index">The index of the child to get.</param>
			//			/// <returns>The child of the given index or null if non-existent.</returns>
			//			internal Node this[<#= child_index_type #> child_index]
			//			{
			//				get
			//				{
			//					if (Children is null)
			//						return null;
			//					if (Children.Length == OmnitreePointsLinked<T, <#= chain_AxisX #>>._children_per_node)
			//						return Children[(int)child_index];
			//					foreach (Node node in Children)
			//						if (node.Index == child_index)
			//							return node;
			//					return null;
			//				}
			//				set
			//				{
			//					// This error check should be unnecessary... but fuck it... might as well
			//					if (value.Index != child_index)
			//						throw new System.Exception("Bug in Omnitree (index/property mis-match when setting a child on a branch)");

			//					// no children yet
			//					if (Children is null)
			//					{
			//						Children = Ɐ(value);
			//						return;
			//					}
			//					// max children overwrite
			//					else if (Children.Length == OmnitreePointsLinked<T, <#= chain_AxisX #>>._children_per_node)
			//					{
			//						Children[(int)child_index] = value;
			//						return;
			//					}
			//					// non-max child overwrite
			//					for (int i = 0; i < Children.Length; i++)
			//						if (Children[i].Index == child_index)
			//						{
			//							Children[i] = value;
			//							return;
			//						}
			//					// new child
			//					Node[] newArray = new Node[Children.Length + 1];
			//					if (newArray.Length == OmnitreePointsLinked<T, <#= chain_AxisX #>>._children_per_node)
			//					{
			//						// new child resulting in a max children branch (sorting required)
			//						for (int i = 0; i < Children.Length; i++)
			//						{
			//							newArray[(int)Children[i].Index] = Children[i];
			//						}
			//						newArray[(int)value.Index] = value;
			//					}
			//					else
			//					{
			//						// new child resulting in a non-max children branch
			//						Array.Copy(Children, newArray, Children.Length);
			//						newArray[newArray.Length - 1] = value;
			//					}
			//					Children = newArray;
			//				}
			//			}

			//			/// <summary>The depth this node is located in the Omnitree.</summary>
			//			internal int Depth
			//			{
			//				get
			//				{
			//					int depth = -1;
			//					for (Node node = this; !(node is null); node = node.Parent)
			//						depth++;
			//					return depth;
			//				}
			//			}

			//			/// <summary>Constructs a node.</summary>
			//			/// <param name="bounds">The bounds of this node.</param>
			//			/// <param name="parent">The parent of this node.</param>
			//			/// <param name="index">The number of elements stored in this node and its children.</param>
			//			internal Node(Omnitree.Bounds<<#= chain_AxisX #>> bounds, Node parent, <#= child_index_type #> index)
			//			{
			//				Bounds = bounds;
			//				Parent = parent;
			//				Index = index;
			//			}

			//			internal Node(Omnitree.Vector<<#= chain_AxisX #>> pointOfDivision, Omnitree.Bounds<<#= chain_AxisX #>> bounds, Node parent, <#= child_index_type #> index)
			//				: this(bounds, parent, index)
			//			{
			//				PointOfDivision = pointOfDivision;
			//			}

			//			internal Node(Node nodeToClone)
			//			{
			//				this.Bounds = nodeToClone.Bounds;
			//				this.Parent = nodeToClone.Parent;
			//				this.Index = nodeToClone.Index;
			//				this.Count = nodeToClone.Count;

			//				Children = nodeToClone.Children.Clone() as Node[];
			//				PointOfDivision = nodeToClone.PointOfDivision;

			//				ValueNode a = this.Head;
			//				ValueNode b = nodeToClone.Head;

			//				while (!(b is null))
			//				{
			//					a.Next = new ValueNode(b.Next.Value, null);
			//					a = a.Next;
			//					b = b.Next;
			//				}
			//			}

			//			internal void Add(T addition)
			//			{
			//				Head = new ValueNode(addition, Head);
			//				Count++;
			//			}

			//			internal Node Clone() =>
			//				new Node(this);
			//		}

			//#endregion

			//#region Constructors

			//		/// <summary>This constructor is for cloning purposes</summary>
			//		internal OmnitreeBoundsLinked(OmnitreeBoundsLinked<T, <#= chain_AxisX #>> omnitree)
			//		{
			//			this._top = omnitree._top.Clone();
			//			this._load = omnitree._load;
			//			this._getBounds = omnitree._getBounds;
			//<# for (int j = 1; j <= i; j++) { #>
			//			this._defaultCompare<#= j #> = omnitree._defaultCompare<#= j #>;
			//			this._compare<#= j #> = omnitree._compare<#= j #>;
			//<# } #>
			//<# for (int j = 1; j <= i; j++) { #>
			//			this._subdivisionOverride<#= j #> = omnitree._subdivisionOverride<#= j #>;
			//<# } #>
			//		}

			//		internal OmnitreeBoundsLinked(
			//			Omnitree.GetBounds<T, <#= chain_AxisX #>> getBounds,
			//<# for (int j = 1; j <= i; j++) { #>
			//			bool defaultCompare<#= j #>,
			//			Compare<Axis<#= j #>> compare<#= j #>,
			//<# } #>
			//			Omnitree.SubdivisionOverride<T, Axis1, Omnitree.Bounds<<#= chain_AxisX #>>> subdivisionOverride1
			//<# for (int j = 2; j <= i; j++) { #>,
			//			Omnitree.SubdivisionOverride<T, Axis<#= j #>, Omnitree.Bounds<<#= chain_AxisX #>>> subdivisionOverride<#= j #>
			//<# } #>
			//			)
			//		{
			//			if (getBounds is null)
			//			{
			//				throw new ArgumentNullException(nameof(getBounds));
			//			}
			//<# for (int j = 1; j <= i; j++) { #>
			//			if (compare<#= j #> is null)
			//			{
			//				throw new ArgumentNullException(nameof(compare<#= j #>));
			//			}
			//<# } #>
			//			this._getBounds = getBounds;
			//<# for (int j = 1; j <= i; j++) { #>
			//			this._defaultCompare<#= j #> = defaultCompare<#= j #>;
			//			this._compare<#= j #> = compare<#= j #>;
			//<# } #>
			//<# for (int j = 1; j <= i; j++) { #>
			//			this._subdivisionOverride<#= j #> = subdivisionOverride<#= j #>;
			//<# } #>
			//			this._top = new Node(Omnitree.Bounds<<#= chain_AxisX #>>.None, null, -1);
			//			Omnitree.ComputeLoads(_top.Count, ref _naturalLogLower, ref _naturalLogUpper, ref _load);
			//		}

			//		/// <summary>Constructs a new <#= i #>D omnitree that stores bounds.</summary>
			//		/// <param name="getBounds">The delegate for getting object bounds in <#= i #>D space.</param>
			//<# for (int j = 1; j <= i; j++) { #>

			//		/// <param name="compare<#= j #>">The delegate for comparing values along the <#= j #>D axis.</param>
			//<# } #>
			//<# for (int j = 1; j <= i; j++) { #>

			//		/// <param name="subdivisionOverride<#= j #>">The subdivision overide to be used when splitting the <#= j #> dimension.</param>
			//<# } #>
			//		public OmnitreeBoundsLinked(
			//			Omnitree.GetBounds<T, <#= chain_AxisX #>> getBounds,
			//<# for (int j = 1; j <= i; j++) { #>
			//			Compare<Axis<#= j #>> compare<#= j #> = null,
			//<# } #>
			//			Omnitree.SubdivisionOverride<T, Axis1, Omnitree.Bounds<<#= chain_AxisX #>>> subdivisionOverride1 = null
			//<# for (int j = 2; j <= i; j++) { #>,
			//			Omnitree.SubdivisionOverride<T, Axis<#= j #>, Omnitree.Bounds<<#= chain_AxisX #>>> subdivisionOverride<#= j #> = null
			//<# } #>
			//			)
			//			: this(
			//			getBounds,
			//<# for (int j = 1; j <= i; j++) { #>
			//			compare<#= j #> is null ? true : false,
			//			compare<#= j #> ?? Compare.Default,
			//<# } #>
			//			subdivisionOverride1
			//<# for (int j = 2; j <= i; j++) { #>,
			//			subdivisionOverride<#= j #>
			//<# } #>
			//			) { }

			//		/// <summary>Constructs a new <#= i #>D omnitree that stores bounds.</summary>
			//		/// <param name="getBoundings">The delegate for getting object bounds in <#= i #>D space.</param>
			//<# for (int j = 1; j <= i; j++) { #>
			//		/// <param name="compare<#= j #>">The delegate for comparing values along the <#= j #>D axis.</param>
			//<# } #>
			//<# for (int j = 1; j <= i; j++) { #>

			//		/// <param name="subdivisionOverride<#= j #>">The subdivision overide to be used when splitting the <#= j #> dimension.</param>
			//<# } #>
			//		public OmnitreeBoundsLinked(
			//			Omnitree.GetBoundings<T, <#= chain_AxisX #>> getBoundings,
			//<# for (int j = 1; j <= i; j++) { #>
			//			Compare<Axis<#= j #>> compare<#= j #> = null,
			//<# } #>
			//			Omnitree.SubdivisionOverride<T, Axis1, Omnitree.Bounds<<#= chain_AxisX #>>> subdivisionOverride1 = null
			//<# for (int j = 2; j <= i; j++) { #>
			//			, Omnitree.SubdivisionOverride<T, Axis<#= j #>, Omnitree.Bounds<<#= chain_AxisX #>>> subdivisionOverride<#= j #> = null
			//<# } #>
			//			)
			//			: this(
			//			Omnitree.ConvertToGetBounds(getBoundings),
			//<# for (int j = 1; j <= i; j++) { #>
			//			compare<#= j #> is null ? true : false,
			//			compare<#= j #> ?? Compare.Default,
			//<# } #>
			//			subdivisionOverride1
			//<# for (int j = 2; j <= i; j++) { #>,
			//			subdivisionOverride<#= j #>
			//<# } #>
			//			) { }

			//#endregion

			//#region Properties

			//		/// <summary>The number of dimensions in this tree.</summary>
			//		public int Dimensions => _dimensions;

			//		/// <summary>The delegate being used by the omnitree to locate items in <#= i #>D space.</summary>
			//		public Omnitree.GetBounds<T, Axis1
			//<# for (int j = 2; j <= i; j++) { #>
			//			, Axis<#= j #>
			//<# } #>
			//			> GetBounds => _getBounds;


			//<# for (int j = 1; j <= i; j++) { #>
			//		/// <summary>The comparison function the Omnitree is using along the <#= j #>D axis.</summary>
			//		public Compare<Axis<#= j #>> Compare<#= j #> => _compare<#= j #>;
			//<# } #>

			//		/// <summary>The current number of items in the tree.</summary>
			//		public int Count  => _top.Count;

			//		internal delegate void MaxDepthFinder(Node node, int current_depth, ref int max_depth);
			//		/// <summary>Finds the current maximum depth of the tree. NOT AN O(1) OPERATION. Intended for educational purposes only.</summary>
			//		public int MaxDepth
			//		{
			//			get
			//			{
			//				MaxDepthFinder maxDepthFinder = null;
			//				maxDepthFinder =
			//						(Node node, int current_depth, ref int max_depth) =>
			//						{
			//							if (current_depth > max_depth)
			//								max_depth = current_depth;
			//							foreach (Node child in node.Children)
			//								maxDepthFinder(child, current_depth + 1, ref max_depth);
			//						};
			//				int _max_depth = -1;
			//				maxDepthFinder(this._top, 0, ref _max_depth);
			//				return _max_depth;
			//			}
			//		}

			//		internal delegate void NodeCountFinder(Node node, ref int current_count);
			//		/// <summary>Counts the current number of nodes in the tree. NOT AN O(1) OPERATION. Intended for educational purposes only.</summary>
			//		public int NodeCount
			//		{
			//			get
			//			{
			//				NodeCountFinder nodeCountFinder = null;
			//				nodeCountFinder =
			//						(Node node, ref int current_count) =>
			//						{
			//							current_count++;
			//							foreach (Node child in node.Children)
			//								nodeCountFinder(child, ref current_count);
			//						};

			//				int _current_count = 0;
			//				nodeCountFinder(this._top, ref _current_count);
			//				return _current_count;
			//			}
			//		}

			//#endregion

			//#region Methods

			//#region Add

			//<# if (false) { #>
			//#region Bulk

			//		// not yet implemented

			////		public void Add(ArrayJagged<T> additions, bool allowMultithreading)
			////		{
			////			if (additions.Length > int.MaxValue)
			////				throw new System.Exception("The maximum size of the Omnitree was exceeded during bulk addition.");
			////
			////			if (this._top.Count != 0 || (int)additions.Length <= _load)
			////			{
			////				for (ulong i = 0; i < additions.Length; i++)
			////					this.Add(additions[i]);
			////			}
			////			else
			////			{
			////				// adjust the loads prior to additions
			////				ComputeLoads((int)additions.Length);
			////
			////				Node new_top = new Node(Omnitree.Bounds<<#= chain_AxisX #>>.None, null, -1);
			////				new_top.Count = (int)additions.Length;
			////
			////
			//<# for (int j = 1; j <= i; j++) { #>
			////				// prepare data for median computations
			////				ArrayJagged<Axis<#= j #>> values<#= j #>;
			////				IAsyncResult result<#= j #> = null;
			////				if (!(this._subdivisionOverride<#= j #> is null))
			////					values<#= j #> = null;
			////				else
			////				{
			////					values<#= j #> = null;
			////					ParallelThread.Operation operation = () =>
			////					{
			////						values<#= j #> = new ArrayJagged<Axis<#= j #>>(additions.Length * 2);
			////						for (ulong i = 0; i < additions.Length; i++)
			////						{
			////							Omnitree.Bounds<<#= chain_AxisX #>> bounds = GetBoundings(additions[i]);
			////							values<#= j #>[i * 2] = bounds.Min1;
			////							values<#= j #>[i * 2 + 1] = bounds.Max1;
			////						}
			////
			////						Towel.Algorithms.Sort.Merge(this._compare<#= j #>, (int i) => { return values<#= j #>[(ulong)i]; }, (int i, Axis<#= j #> value) => { values<#= j #>[(ulong)i] = value; }, 0, (int)(additions.Length - 1));
			////					};
			////
			////					if (allowMultithreading)
			////						result<#= j #> = ParallelThread.Run(operation);
			////					else
			////						operation();
			////				}
			////
			//<# } #>
			////
			////
			//<# for (int j = 1; j <= i; j++) { #>
			////				if (this._subdivisionOverride<#= j #> is null && allowMultithreading)
			////					result<#= j #>.AsyncWaitHandle.WaitOne();
			//<# } #>
			////
			////				// build the tree
			////				Add(new_top, 1, -1, additions.ToStepper(), (int)additions.Length, 
			//<# for (int j = 1; j <= i; j++) { #>int.MinValue, 
			//<# } #>(int)additions.Length, 
			//<# for (int j = 1; j <= i; j++) { #>(int index) => { return values<#= j #>[index]; }, 
			//<# } #>allowMultithreading);
			////				
			////				this._top = new_top;
			////			}
			////		}
			////
			////		public void Add(bool allowMultithreading, params T[] additions)
			////		{
			////			if (additions.Length > int.MaxValue)
			////				throw new System.Exception("The maximum size of the Omnitree was exceeded during bulk addition.");
			////
			////			if (this._top.Count != 0 || (int)additions.Length <= _load)
			////			{
			////				for (int i = 0; i < additions.Length; i++)
			////					this.Add(additions[i]);
			////			}
			////			else
			////			{
			////				// adjust the loads prior to additions
			////				ComputeLoads((int)additions.Length);
			////
			////				Node new_top = new Node(Omnitree.Bounds<<#= chain_AxisX #>>.None, null, -1);
			////				new_top.Count = (int)additions.Length;
			////
			////
			//<# for (int j = 1; j <= i; j++) { #>
			////				// prepare data for median computations
			////				ArrayJagged<Axis<#= j #>> values<#= j #>;
			////				IAsyncResult result<#= j #> = null;
			////				if (!(this._subdivisionOverride<#= j #> is null))
			////					values<#= j #> = null;
			////				else
			////				{
			////					values<#= j #> = null;
			////					ParallelThread.Operation operation = () =>
			////					{
			////						values<#= j #> = new ArrayJagged<Axis<#= j #>>(additions.Length);
			////						for (int i = 0; i < additions.Length; i++)
			////							values<#= j #>[i] = LocateVector(additions[i]).Axis<#= j #>;
			////						Towel.Algorithms.Sort.Merge(this._compare<#= j #>, (int i) => { return values<#= j #>[(ulong)i]; }, (int i, Axis<#= j #> value) => { values<#= j #>[(ulong)i] = value; }, 0, (int)(additions.Length - 1));
			////					};
			////
			////					if (allowMultithreading)
			////						result<#= j #> = ParallelThread.Run(operation);
			////					else
			////						operation();
			////				}
			////
			//<# } #>
			////
			////
			//<# for (int j = 1; j <= i; j++) { #>
			////				if (this._subdivisionOverride<#= j #> is null && allowMultithreading)
			////					result<#= j #>.AsyncWaitHandle.WaitOne();
			////
			//<# } #>
			////
			////				// build the tree
			////				Add(new_top, 1, -1, additions.ToStepper(), additions.Length, 
			//<# for (int j = 1; j <= i; j++) { #>int.MinValue, 
			//<# } #>(int)additions.Length, 
			//<# for (int j = 1; j <= i; j++) { #>(int index) => { return values<#= j #>[index]; }, 
			//<# } #>allowMultithreading);
			////				
			////				this._top = new_top;
			////			}
			////		}
			////
			////		
			////		internal int Add(Node parent, int depth, <#= child_index_type #> child, Action<Action<T>> additions, int parent_count, 
			//<# for (int j = 1; j <= i; j++) { #>int prevmed<#= j #>, 
			//<# } #>int initial_count, 
			//<# for (int j = 1; j <= i; j++) { #>GetIndex<Axis<#= j #>> values<#= j #>, 
			//<# } #>bool allowMultithreading)
			////		{
			//<# for (int j = 1; j <= i; j++) { #>
			////			Axis<#= j #> pointOfDivision<#= j #>;
			//<# } #>
			////
			//<# for (int j = 1; j <= i; j++) { #>
			////			int median_axis<#= j #> = -1;
			//<# } #>
			////			if (this._subdivisionOverride1 is null
			//<# for (int j = 2; j <= i; j++) { #> || this._subdivisionOverride<#= j #> is null
			//<# } #>)
			////				GetMedianIndexes(initial_count, child, depth, 
			//<# for (int j = 1; j <= i; j++) { #>prevmed<#= j #>, 
			//<# } #>out median_axis1
			//<# for (int j = 2; j <= i; j++) { #>, out median_axis<#= j #>
			//<# } #>);
			////
			//<# for (int j = 1; j <= i; j++) { #>
			////			if (!(this._subdivisionOverride<#= j #> is null))
			////				pointOfDivision<#= j #> = this._subdivisionOverride<#= j #>(parent.Bounds, additions);
			////			else
			////				pointOfDivision<#= j #> = values<#= j #>(median_axis<#= j #>);
			////
			//<# } #>
			////			parent.PointOfDivision = new Omnitree.Vector<<#= chain_AxisX #>>(pointOfDivision1
			//<# for (int j = 2; j <= i; j++) { #>, pointOfDivision<#= j #>
			//<# } #>);
			////
			////			// divide the values along the medians
			////			IMap<IList<T>, <#= child_index_type #>> collection_map = new MapHashLinked<IList<T>, <#= child_index_type #>>();
			////			additions((T value) => 
			////			{
			////				<#= child_index_type #> index = DetermineChildIndex(parent.PointOfDivision.Value, LocateVector(value));
			////				IList<T> list = null;
			////				if (collection_map.TryGet(index, out list))
			////				{
			////					list.Add(value);
			////				}
			////				else
			////				{
			////					if (parent_count < 100000)
			////						list = new ListArray<T>();
			////					else
			////						list = new ListLinked<T>();
			////					collection_map.Add(index, list);
			////					list.Add(value);
			////				}
			////			});
			////
			////			if (depth == 1 && allowMultithreading)
			////			{
			////				// NOTE: Must assign placeholders before multithreading so that the threads do not overwrite each other
			////				collection_map.Keys((<#= child_index_type #> key) => { parent[key] = new Node(Omnitree.Bounds<<#= chain_AxisX #>>.None, parent, key); });
			////				IAsyncResult[] handles = new IAsyncResult[Environment.ProcessorCount];
			////				for (int i = 0; i < handles.Length; i++)
			////				{
			////					int multiTheadSafe_i = i; // used as catpure variable below making it multithread-safe
			////					handles[i] = ParallelThread.Run(() =>
			////					{
			////						Step.EveryNth<Link<IList<T>, <#= child_index_type #>>>(collection_map.Pairs, multiTheadSafe_i + 1)(
			////						(Link<IList<T>, <#= child_index_type #>> link) =>
			////							{
			////								ReversedChildBuilding(parent, link._2, depth, link._1.Stepper, link._1.Count, 
			//<# for (int j = 1; j <= i; j++) { #>median_axis<#= j #>, 
			//<# } #>initial_count, 
			//<# for (int j = 1; j <= i; j++) { #>values<#= j #>, 
			//<# } #>allowMultithreading);
			////							});
			////					});
			////				}
			////				
			////				foreach (IAsyncResult handle in handles)
			////				{
			////					handle.AsyncWaitHandle.WaitOne();
			////				}
			////			}
			////			else
			////			{
			////				collection_map.Pairs((Link<IList<T>, <#= child_index_type #>> link) =>
			////				{ 
			////					ReversedChildBuilding(parent, link._2, depth, link._1.Stepper, link._1.Count, 
			//<# for (int j = 1; j <= i; j++) { #>median_axis<#= j #>, 
			//<# } #>initial_count, 
			//<# for (int j = 1; j <= i; j++) { #>values<#= j #>, 
			//<# } #>allowMultithreading);
			////				});
			////			}
			////
			////			int count = 0;
			////			foreach (Node node in parent.Children)
			////				count += node.Count;
			////			return count;
			////		}
			////
			////		int ReversedChildBuilding(Node parent, <#= child_index_type #> child_index, int depth, Action<Action<T>> additions, int count, 
			//<# for (int j = 1; j <= i; j++) { #>int prevmed<#= j #>, 
			//<# } #>int initial_count, 
			//<# for (int j = 1; j <= i; j++) { #>GetIndex<Axis<#= j #>> values<#= j #>, 
			//<# } #>bool allowMultithreading)
			////		{
			////			Omnitree.Bounds<<#= chain_AxisX #>> child_bounds = DetermineChildBounds(parent, child_index);
			////			if (depth >= _load || count <= _load)
			////			{
			////				Node new_leaf = new Node(child_bounds, parent, child_index);
			////				additions((T value) => { new_leaf.Add(value); });
			////				parent[new_leaf.Index] = new_leaf;
			////				return new_leaf.Count;
			////			}
			////			else
			////			{
			////				Node new_branch = new Node(Omnitree.Vector<<#= chain_AxisX #>>.Default, child_bounds, parent, child_index);
			////				parent[new_branch.Index] = new_branch;
			////				new_branch.Count = Add(new_branch, depth + 1, child_index, additions, count, 
			//<# for (int j = 1; j <= i; j++) { #>prevmed<#= j #>, 
			//<# } #>count, 
			//<# for (int j = 1; j <= i; j++) { #>values<#= j #>, 
			//<# } #>allowMultithreading);
			////				return new_branch.Count;
			////			}
			////		}
			////
			////		/// <summary>Gets the indeces of the median values at the given position during bulk additions.</summary>
			////		internal void GetMedianIndexes(int count, <#= child_index_type #> child_index, int depth, 
			//<# for (int j = 1; j <= i; j++) { #>int previous<#= j #>, 
			//<# } #>out int index1
			//<# for (int j = 2; j <= i; j++) { #>, out int index<#= j #>
			//<# } #>)
			////		{
			////			if (depth == 1)
			////			{
			//<# for (int j = 1; j <= i; j++) { #>
			////				index<#= j #> = (count - 1) / 2;
			//<# } #>
			////				return;
			////			}
			////
			////			int splits = Compute.Power(2, depth);
			////			int mid_child_range = count / splits;
			////
			//<# for (int j = i; j >= 1; j--) { #>
			////			if (child_index >= <#= (2 << (j - 1)) / 2 #>)
			////			{
			////				index<#= j #> = previous<#= j #> + mid_child_range;
			////				child_index -= <#= (2 << (j - 1)) / 2 #>;
			////			}
			////			else
			////			{
			////				index<#= j #> = previous<#= j #> - mid_child_range;
			////			}
			////
			//<# } #>
			////		}

			//#endregion

			//<# } #>

			//#region single

			//		/// <summary>Tries to add a value.</summary>
			//		/// <param name="value">The value to be added.</param>
			//		/// <param name="exception">The exception that occurred if the add failed.</param>
			//		/// <returns>True if successful or false if not.</returns>
			//		public bool TryAdd(T value, out Exception exception)
			//		{
			//			Add(value);
			//			exception = null;
			//			return true;
			//		}

			//		/// <summary>Adds an item to the tree.</summary>
			//		/// <param name="addition">The item to be added.</param>
			//		public void Add(T addition)
			//		{
			//			if (this._top.Count == int.MaxValue)
			//				throw new System.InvalidOperationException("(Count == int.MaxValue) max Omnitree size reached (change ints to longs if you need to).");

			//			// dynamic tree sizes
			//			Omnitree.ComputeLoads(_top.Count, ref _naturalLogLower, ref _naturalLogUpper, ref _load);

			//			Omnitree.Bounds<<#= chain_AxisX #>> bounds = GetBoundings(addition);

			//			// grow the first branch of the tree
			//			if (!this._top.PointOfDivision.HasValue && this._top.Count >= _load)
			//			{
			//				Node top = this._top;

			//				// create the new branch from the median values
			//				this._top = new Node(DetermineMedians(top), Omnitree.Bounds<<#= chain_AxisX #>>.None, null, -1);

			//				// iterate through the elements and add them to the appropriate children
			//				for (Node.ValueNode list = top.Head; !(list is null); list = list.Next)
			//					Add(list.Value, this._top, GetBoundings(list.Value), 0);
			//			}

			//			this.Add(addition, this._top, bounds, 0);
			//		}

			//		/// <summary>Recursive version of the add function.</summary>
			//		/// <param name="addition">The item to be added.</param>
			//		/// <param name="node">The current node for tree trversal.</param>
			//		/// <param name="bounds">The bounds of the addition.</param>
			//		/// <param name="depth">The current depth of iteration.</param>
			//		internal void Add(T addition, Node node, Omnitree.Bounds<<#= chain_AxisX #>> bounds, int depth)
			//		{
			//			if (!node.PointOfDivision.HasValue)
			//			{
			//				//Leaf leaf = node as Leaf;
			//				if (depth >= _load || !(node.Count >= _load))
			//				{
			//					node.Add(addition);
			//					return;
			//				}
			//				else
			//				{
			//					//Node parent = node.Parent;
			//					//<#= child_index_type #> child_index = this.DetermineChildIndex(parent.PointOfDivision, location);
			//					//Node growth = new Node(DetermineMedians(leaf), leaf.Bounds, parent, child_index);
			//					//parent[child_index] = growth;

			//					Node growth = new Node(DetermineMedians(node), node.Bounds, node.Parent, node.Index);
			//					node.Parent[node.Index] = growth;

			//					for (Node.ValueNode list = node.Head; !(list is null); list = list.Next)
			//					{
			//						Omnitree.Bounds<<#= chain_AxisX #>> temp_bounds = GetBoundings(list.Value);
			//						if (EncapsulationCheck(growth.Bounds, temp_bounds))
			//							Add(list.Value, growth, temp_bounds, depth);
			//						else
			//						{
			//							ReduceParentCounts(node.Parent, 1);
			//							Add(list.Value, this._top, temp_bounds, depth);
			//						}
			//					}

			//					Add(addition, growth, bounds, depth);
			//					return;
			//				}
			//			}
			//			else
			//			{
			//				//Node branch = node as Node;
			//				<#= child_index_type #> child_index = this.DetermineChildIndex(node.PointOfDivision.Value, bounds); // determine the child "index" (0 through 2^Dimensions) the addition belongs in

			//				// if -1, then the bounds of the addition straddle the point of division (keep it in current node)
			//				if (child_index == -1)
			//				{
			//					node.Add(addition);
			//					return;
			//				}

			//				Node child_node = node[child_index];

			//				// null children in branches are just empty leaves
			//				if (child_node is null)
			//				{
			//					Node new_node = new Node(DetermineChildBounds(node, child_index), node, child_index);
			//					node[child_index] = new_node;
			//					new_node.Add(addition);
			//				}
			//				else
			//					// child exists already, continue adding
			//					Add(addition, child_node, bounds, depth + 1);

			//				node.Count++;
			//				return;
			//			}
			//		}

			//		internal Omnitree.Vector<<#= chain_AxisX #>> DetermineMedians(Node node)
			//		{
			//			try
			//			{
			//				// extract the values
			//<# for (int j = 1; j <= i; j++) { #>
			//				Omnitree.Bound<Axis<#= j #>>[] values<#= j #> = new Omnitree.Bound<Axis<#= j #>>[node.Count * 2];
			//<# } #>
			//				Node.ValueNode for_current = node.Head; // used in for loop
			//				for (int i = 0; i < node.Count; i++, for_current = for_current.Next)
			//					this._getBounds(for_current.Value, 
			//					out values1[i * 2], out values1[i * 2 + 1]
			//<# for (int j = 2; j <= i; j++) { #>, 
			//					out values<#= j #>[i * 2], out values<#= j #>[i * 2 + 1]
			//<# } #>
			//					);
			//				return new Omnitree.Vector<<#= chain_AxisX #>>(
			//					Omnitree.SubDivide(values1, this._defaultCompare1 ? Compare.Default : this._compare1)
			//<# for (int j = 2; j <= i; j++) { #>, 
			//					Omnitree.SubDivide(values<#= j #>, this._defaultCompare<#= j #> ? Compare.Default : this._compare<#= j #>)
			//<# } #>
			//					);
			//			}
			//			catch
			//			{
			//				// extract the values
			//<# for (int j = 1; j <= i; j++) { #>
			//				ArrayJagged<Omnitree.Bound<Axis<#= j #>>> values<#= j #> = new ArrayJagged<Omnitree.Bound<Axis<#= j #>>>(node.Count * 2);
			//<# } #>
			//				Node.ValueNode for_current = node.Head; // used in for loop
			//				for (int i = 0; i < node.Count; i++, for_current = for_current.Next)
			//				{
			//<# for (int j = 1; j <= i; j++) { #>
			//					Omnitree.Bound<Axis<#= j #>> min<#= j #>; Omnitree.Bound<Axis<#= j #>> max<#= j #>;
			//<# } #>
			//					this._getBounds(for_current.Value,
			//						out min1, out max1
			//<# for (int j = 2; j <= i; j++) { #>,
			//						out min<#= j #>, out max<#= j #>
			//<# } #>
			//						);
			//<# for (int j = 1; j <= i; j++) { #>
			//					values<#= j #>[i * 2] = min<#= j #>; values<#= j #>[i * 2 + 1] = max<#= j #>;
			//<# } #>
			//				}
			//				return new Omnitree.Vector<<#= chain_AxisX #>>(
			//					Omnitree.SubDivide(values1, this._defaultCompare1 ? Compare.Default : this._compare1)
			//<# for (int j = 2; j <= i; j++) { #>
			//					, Omnitree.SubDivide(values<#= j #>, this._defaultCompare<#= j #> ? Compare.Default : this._compare<#= j #>)
			//<# } #>
			//				);
			//			}
			//		}

			//#endregion

			//#region Add Helpers

			//		internal Omnitree.Bounds<<#= chain_AxisX #>> DetermineChildBounds(Node node, <#= child_index_type #> child_index)
			//		{
			//			// the node parameter should always have a point of division value for this function
			//			Omnitree.Vector<<#= chain_AxisX #>> pointOfDivision = node.PointOfDivision.Value;

			//<# for (int j = i; j >= 1; j--) { #>
			//			Omnitree.Bound<Axis<#= j #>> min<#= j #>, max<#= j #>;
			//			if (child_index >= <#= (2 << (j - 1)) / 2 #>)
			//			{
			//				min<#= j #> = pointOfDivision.Axis<#= j #>;
			//				max<#= j #> = node.Bounds.Max<#= j #>;
			//				child_index -= <#= (2 << (j - 1)) / 2 #>;
			//			}
			//			else
			//			{
			//				min<#= j #> = node.Bounds.Min<#= j #>;
			//				max<#= j #> = pointOfDivision.Axis<#= j #>;
			//			}

			//<# } #>
			//			return new Omnitree.Bounds<<#= chain_AxisX #>>(<#= chain_minX_maxX #>);
			//		}

			//#endregion

			//#endregion

			//#region Clear

			//		/// <summary>Returns the tree to an empty state.</summary>
			//		public void Clear()
			//		{
			//			this._top = new Node(Omnitree.Bounds<<#= chain_AxisX #>>.None, null, -1);
			//			Omnitree.ComputeLoads(_top.Count, ref _naturalLogLower, ref _naturalLogUpper, ref _load);
			//		}

			//#endregion

			//#region Clone

			//		/// <summary>Creates a shallow clone of this data structure.</summary>
			//		/// <returns>A shallow clone of this data structure.</returns>
			//		public OmnitreeBoundsLinked<T, <#= chain_AxisX #>> Clone()
			//		{
			//			return new OmnitreeBoundsLinked<T, <#= chain_AxisX #>>(this);
			//		}

			//#endregion

			//#region Count

			//		/// <summary>Counts the number of items encapsulated by a sub space.</summary>
			//		<#= documentation_AxisX_minX_AxisX_maxX #>
			//		/// <returns>The number of items in the provided sub space.</returns>
			//		public int CountSubSpaceEncapsulated(<#= chain_AxisX_minX_AxisX_maxX #>)
			//		{
			//			return CountSubSpaceEncapsulated(_top, new Omnitree.Bounds<<#= chain_AxisX #>>(<#= chain_minX_maxX #>));
			//		}
			//		/// <summary>Counts the number of items encapsulated by a sub space.</summary>
			//		<#= documentation_AxisX_minX_AxisX_maxX #>
			//		/// <returns>The number of items in the provided sub space.</returns>
			//		public int CountSubSpaceEncapsulated(<#= chain_BoundAxisX_minX_BoundAxisX_maxX #>)
			//		{
			//			return CountSubSpaceEncapsulated(_top, new Omnitree.Bounds<<#= chain_AxisX #>>(<#= chain_minX_maxX #>));
			//		}
			//		/// <summary>Counts the number of items encapsulated by a sub space.</summary>
			//		<#= documentation_AxisX_axisX #>
			//		/// <returns>The number of items in the provided sub space.</returns>
			//		public int CountSubSpaceEncapsulated(<#= chain_AxisX_axisX #>)
			//		{
			//			return CountSubSpaceEncapsulated(_top, new Omnitree.Bounds<<#= chain_AxisX #>>(<#= chain_axisX_axisX #>));
			//		}
			//		/// <summary>Counts the number of items encapsulated by a sub space.</summary>
			//		<#= documentation_AxisX_axisX #>
			//		/// <returns>The number of items in the provided sub space.</returns>
			//		public int CountSubSpaceEncapsulated(<#= chain_BoundAxisX_axisX #>)
			//		{
			//			return CountSubSpaceEncapsulated(_top, new Omnitree.Bounds<<#= chain_AxisX #>>(<#= chain_axisX_axisX #>));
			//		}

			//		/// <summary>Counts the number of items overlapped by a sub space.</summary>
			//		<#= documentation_AxisX_minX_AxisX_maxX #>
			//		/// <returns>The number of items in the provided sub space.</returns>
			//		public int CountSubSpaceOverlapped(<#= chain_AxisX_minX_AxisX_maxX #>)
			//		{
			//			return CountSubSpaceOverlapped(_top, new Omnitree.Bounds<<#= chain_AxisX #>>(<#= chain_minX_maxX #>));
			//		}
			//		/// <summary>Counts the number of items overlapped by a sub space.</summary>
			//		<#= documentation_AxisX_minX_AxisX_maxX #>
			//		/// <returns>The number of items in the provided sub space.</returns>
			//		public int CountSubSpaceOverlapped(<#= chain_BoundAxisX_minX_BoundAxisX_maxX #>)
			//		{
			//			return CountSubSpaceOverlapped(_top, new Omnitree.Bounds<<#= chain_AxisX #>>(<#= chain_minX_maxX #>));
			//		}
			//		/// <summary>Counts the number of items overlapped by a sub space.</summary>
			//		<#= documentation_AxisX_axisX #>
			//		/// <returns>The number of items in the provided sub space.</returns>
			//		public int CountSubSpaceOverlapped(<#= chain_AxisX_axisX #>)
			//		{
			//			return CountSubSpaceOverlapped(_top, new Omnitree.Bounds<<#= chain_AxisX #>>(<#= chain_axisX_axisX #>));
			//		}
			//		/// <summary>Counts the number of items overlapped by a sub space.</summary>
			//		<#= documentation_AxisX_axisX #>
			//		/// <returns>The number of items in the provided sub space.</returns>
			//		public int CountSubSpaceOverlapped(<#= chain_BoundAxisX_axisX #>)
			//		{
			//			return CountSubSpaceOverlapped(_top, new Omnitree.Bounds<<#= chain_AxisX #>>(<#= chain_axisX_axisX #>));
			//		}

			//		internal int CountSubSpaceEncapsulated(Node node, Omnitree.Bounds<<#= chain_AxisX #>> bounds)
			//		{
			//			return CountSubSpaceBase(_top, bounds, (a, b) => EncapsulationCheck(a, b));
			//		}

			//		internal int CountSubSpaceOverlapped(Node node, Omnitree.Bounds<<#= chain_AxisX #>> bounds)
			//		{
			//			return CountSubSpaceBase(_top, bounds, (a, b) => InclusionCheck(a, b));
			//		}

			//		internal int CountSubSpaceBase(
			//			Node node,
			//			Omnitree.Bounds<<#= chain_AxisX #>> bounds,
			//			Omnitree.SpatialCheck<Omnitree.Bounds<<#= chain_AxisX #>>, Omnitree.Bounds<<#= chain_AxisX #>>> spatialCheck)
			//		{
			//			// adjust min/max values
			//			int count = 0;
			//			if (EncapsulationCheck(bounds, node.Bounds))
			//				count += node.Count;
			//			else if (!node.PointOfDivision.HasValue)
			//			{
			//				for (Node.ValueNode list = node.Head; !(list is null); list = list.Next)
			//					if (spatialCheck(bounds, GetBoundings(list.Value)))
			//						count++;
			//			}
			//			else
			//			{
			//				Node branch = node as Node;
			//				if (!StraddlesLines(branch.Bounds, branch.PointOfDivision.Value))
			//				{
			//					<#= child_index_type #> child_index = DetermineChildIndex(branch.PointOfDivision.Value, bounds);
			//					Node child = branch[child_index];
			//					if (!(child is null))
			//					  count += this.CountSubSpaceBase(child, bounds, spatialCheck);
			//				}
			//				else
			//				{
			//					foreach (Node child in node.Children)
			//						count += this.CountSubSpaceBase(child, bounds, spatialCheck);
			//				}
			//			}
			//			return count;
			//		}

			//#endregion

			//#region Update

			//		/// <summary>Iterates through the entire tree and ensures each item is in the proper leaf.</summary>
			//		public void Update()
			//		{
			//			this.Update(this._top, 0);
			//		}

			//		/// <summary>Recursive version of the Update method.</summary>
			//		/// <param name="node">The current node of iteration.</param>
			//		/// <param name="depth">The current depth of iteration.</param>
			//		internal int Update(Node node, int depth)
			//		{
			//			int removals = 0;

			//			{
			//				Node branch = node as Node;
			//				int skipped = 0;
			//				for (int i = 0; i + skipped < branch.Children.Length; )
			//				{
			//					removals += this.Update(branch.Children[i], depth + 1);
			//					if (branch.Children[i].Count == 0)
			//						branch.Children[i] = branch.Children[branch.Children.Length - skipped++ - 1];
			//					else
			//						i++;
			//				}
			//				Node[] newArray = new Node[branch.Children.Length - skipped];
			//				Array.Copy(branch.Children, newArray, newArray.Length);
			//				branch.Children = newArray;

			//				if (branch.Count < _load && branch.Count != 0)
			//					ShrinkChild(branch.Parent, branch.Index);
			//			}

			//			{
			//				Node.ValueNode current = node.Head;
			//				Node.ValueNode previous = null;
			//				while (!(current is null))
			//				{
			//					Omnitree.Bounds<<#= chain_AxisX #>> bounds = GetBoundings(current.Value);
			//					if (!this.EncapsulationCheck(node.Bounds, bounds))
			//					{
			//						removals++;
			//						T updated = current.Value;
			//						if (previous is null)
			//						{
			//							node.Head = current.Next;
			//							goto HeadRemoved;
			//						}
			//						else
			//							previous.Next = current.Next;

			//						Node whereToAdd = GetEncapsulationParent(node.Parent, bounds);

			//						if (whereToAdd is null)
			//							throw new System.Exception("an item was updated outside the range of the omnitree");

			//						this.Add(updated, whereToAdd, bounds, whereToAdd.Depth);
			//					}
			//					previous = current;
			//				HeadRemoved:
			//					current = current.Next;
			//				}
			//			}

			//			node.Count -= removals;
			//			return removals;
			//		}

			//		/// <summary>Iterates through the provided dimensions and ensures each item is in the proper leaf.</summary>
			//		<#= documentation_AxisX_minX_AxisX_maxX #>
			//		public void Update(<#= chain_AxisX_minX_AxisX_maxX #>)
			//		{
			//			this.Update(new Omnitree.Bounds<<#= chain_AxisX #>>(<#= chain_minX_maxX #>), this._top, 0);
			//		}
			//		/// <summary>Iterates through the provided dimensions and ensures each item is in the proper leaf.</summary>
			//		<#= documentation_AxisX_minX_AxisX_maxX #>
			//		public void Update(<#= chain_BoundAxisX_minX_BoundAxisX_maxX #>)
			//		{
			//			this.Update(new Omnitree.Bounds<<#= chain_AxisX #>>(<#= chain_minX_maxX #>), this._top, 0);
			//		}
			//		/// <summary>Iterates through the provided dimensions and ensures each item is in the proper leaf.</summary>
			//		<#= documentation_AxisX_axisX #>
			//		public void Update(<#= chain_AxisX_axisX #>)
			//		{
			//			this.Update(new Omnitree.Bounds<<#= chain_AxisX #>>(<#= chain_axisX_axisX #>), this._top, 0);
			//		}
			//		/// <summary>Iterates through the provided dimensions and ensures each item is in the proper leaf.</summary>
			//		<#= documentation_AxisX_axisX #>
			//		public void Update(<#= chain_BoundAxisX_axisX #>)
			//		{
			//			this.Update(new Omnitree.Bounds<<#= chain_AxisX #>>(<#= chain_axisX_axisX #>), this._top, 0);
			//		}
			//		internal int Update(Omnitree.Bounds<<#= chain_AxisX #>> bounds, Node node, int depth)
			//		{
			//			if (!InclusionCheck(bounds, node.Bounds))
			//				return 0;

			//			int removals = 0;

			//			{
			//				Node branch = node as Node;
			//				int skipped = 0;
			//				for (int i = 0; i + skipped < branch.Children.Length; )
			//				{
			//					removals += this.Update(branch.Children[i], depth + 1);
			//					if (branch.Children[i].Count == 0)
			//						branch.Children[i] = branch.Children[branch.Children.Length - skipped++ - 1];
			//					else
			//						i++;
			//				}
			//				Node[] newArray = new Node[branch.Children.Length - skipped];
			//				Array.Copy(branch.Children, newArray, newArray.Length);
			//				branch.Children = newArray;

			//				if (branch.Count < _load && branch.Count != 0)
			//					ShrinkChild(branch.Parent, branch.Index);
			//			}

			//			{
			//				Node.ValueNode current = node.Head;
			//				Node.ValueNode previous = null;
			//				while (!(current is null))
			//				{
			//					Omnitree.Bounds<<#= chain_AxisX #>> item_bounds = GetBoundings(current.Value);
			//					if (!this.EncapsulationCheck(node.Bounds, item_bounds))
			//					{
			//						removals++;
			//						T updated = current.Value;
			//						if (previous is null)
			//						{
			//							node.Head = current.Next;
			//							goto HeadRemoved;
			//						}
			//						else
			//							previous.Next = current.Next;
			//						Node whereToAdd = GetEncapsulationParent(node.Parent, item_bounds);
			//						if (whereToAdd is null)
			//							throw new System.Exception("an item was updates outside the range of the omnitree");
			//						this.Add(updated, whereToAdd, item_bounds, whereToAdd.Depth);
			//					}
			//					previous = current;
			//				HeadRemoved:
			//					current = current.Next;
			//				}
			//			}

			//			node.Count -= removals;
			//			return removals;
			//		}

			//#endregion

			//#region Remove

			//		/// <summary>Removes all the items qualified by the delegate.</summary>
			//		/// <param name="where">The predicate to qualify removals.</param>
			//		public void Remove(Predicate<T> where)
			//		{
			//			this.Remove(this._top, where);
			//			Omnitree.ComputeLoads(_top.Count, ref _naturalLogLower, ref _naturalLogUpper, ref _load);
			//		}

			//		/// <summary>Recursive version of the remove method.</summary>
			//		/// <param name="node">The current node of traversal.</param>
			//		/// <param name="where">The predicate to qualify removals.</param>
			//		internal int Remove(Node node, Predicate<T> where)
			//		{
			//			int removals = 0;

			//			// children
			//			if (!(node.Children is null))
			//			{
			//				int skipped = 0;
			//				for (int i = 0; i + skipped < node.Children.Length; )
			//				{
			//					removals += this.Remove(node.Children[i], where);
			//					if (node.Children[i].Count == 0)
			//						node.Children[i] = node.Children[node.Children.Length - skipped++ - 1];
			//					else
			//						i++;
			//				}
			//				Node[] newArray = new Node[node.Children.Length - skipped];
			//				Array.Copy(node.Children, newArray, newArray.Length);
			//				node.Children = newArray;

			//				if (node.Count < _load && node.Count != 0)
			//					ShrinkChild(node.Parent, node.Index);
			//			}

			//			// items
			//			while (!(node.Head is null) && where(node.Head.Value))
			//			{
			//				node.Head = node.Head.Next;
			//				removals++;
			//			}
			//			if (!(node.Head is null))
			//			{
			//				Node.ValueNode list = node.Head;
			//				while (!(list.Next is null))
			//				{
			//					if (where(list.Next.Value))
			//					{
			//						list.Next = list.Next.Next;
			//						removals++;
			//					}
			//				}
			//			}

			//			node.Count -= removals;
			//			return removals;
			//		}

			//		/// <summary>Removes all the items encapsulated in a given space.</summary>
			//		<#= documentation_AxisX_minX_AxisX_maxX #>
			//		/// <returns>The number of items that were removed.</returns>
			//		public void RemoveEncapsulated(<#= chain_AxisX_minX_AxisX_maxX #>)
			//		{
			//			this.RemoveEncapsulated(this._top, new Omnitree.Bounds<<#= chain_AxisX #>>(<#= chain_minX_maxX #>));
			//		}
			//		/// <summary>Removes all the items encapsulated in a given space.</summary>
			//		<#= documentation_AxisX_minX_AxisX_maxX #>
			//		/// <returns>The number of items that were removed.</returns>
			//		public void RemoveEncapsulated(<#= chain_BoundAxisX_minX_BoundAxisX_maxX #>)
			//		{
			//			this.RemoveEncapsulated(this._top, new Omnitree.Bounds<<#= chain_AxisX #>>(<#= chain_minX_maxX #>));
			//		}
			//		/// <summary>Removes all the items encapsulated in a given space.</summary>
			//		<#= documentation_AxisX_axisX #>
			//		public void RemoveEncapsulated(<#= chain_BoundAxisX_axisX #>)
			//		{
			//			this.RemoveEncapsulated(this._top, new Omnitree.Bounds<<#= chain_AxisX #>>(<#= chain_axisX_axisX #>));
			//		}
			//		internal int RemoveEncapsulated(Node node, Omnitree.Bounds<<#= chain_AxisX #>> bounds)
			//		{
			//			int removals = this.RemoveBase(node, bounds, (a, b) => this.EncapsulationCheck(a, b));
			//			Omnitree.ComputeLoads(_top.Count, ref _naturalLogLower, ref _naturalLogUpper, ref _load);
			//			return removals;
			//		}

			//		/// <summary>Removes all the items overlapping a given space.</summary>
			//		<#= documentation_AxisX_minX_AxisX_maxX #>
			//		/// <returns>The number of items that were removed.</returns>
			//		public void RemoveOverlapped(<#= chain_AxisX_minX_AxisX_maxX #>)
			//		{
			//			this.RemoveOverlapped(this._top, new Omnitree.Bounds<<#= chain_AxisX #>>(<#= chain_minX_maxX #>));
			//		}
			//		/// <summary>Removes all the items overlapping a given space.</summary>
			//		<#= documentation_AxisX_minX_AxisX_maxX #>
			//		/// <returns>The number of items that were removed.</returns>
			//		public void RemoveOverlapped(<#= chain_BoundAxisX_minX_BoundAxisX_maxX #>)
			//		{
			//			this.RemoveOverlapped(this._top, new Omnitree.Bounds<<#= chain_AxisX #>>(<#= chain_minX_maxX #>));
			//		}
			//		internal int RemoveOverlapped(Node node, Omnitree.Bounds<<#= chain_AxisX #>> bounds)
			//		{
			//			int removals = this.RemoveBase(node, bounds, (a, b) => this.InclusionCheck(a, b));
			//			Omnitree.ComputeLoads(_top.Count, ref _naturalLogLower, ref _naturalLogUpper, ref _load);
			//			return removals;
			//		}

			//		internal int RemoveBase(
			//			Node node,
			//			Omnitree.Bounds<<#= chain_AxisX #>> bounds,
			//			Omnitree.SpatialCheck<Omnitree.Bounds<<#= chain_AxisX #>>, Omnitree.Bounds<<#= chain_AxisX #>>> spatialCheck)
			//		{
			//			int removals = 0;
			//			if (InclusionCheck(bounds, node.Bounds))
			//			{
			//				// items
			//				Node.ValueNode current_node = node.Head;
			//				Node.ValueNode previous_node = null;
			//				while (!(current_node is null))
			//				{
			//					Node.ValueNode temp_previous = current_node;
			//					if (spatialCheck(bounds, GetBoundings(current_node.Value)))
			//					{
			//						removals++;
			//						if (current_node == node.Head)
			//							node.Head = node.Head.Next;
			//						else
			//						{
			//							previous_node.Next = current_node.Next;
			//							temp_previous = previous_node;
			//						}
			//					}
			//					previous_node = temp_previous;
			//					current_node = current_node.Next;
			//				}

			//				// children
			//				if (!(node.Children is null))
			//				{
			//					int skipped = 0;
			//					for (int i = 0; i + skipped < node.Children.Length; )
			//					{
			//						removals += this.RemoveBase(node.Children[i], bounds, spatialCheck);
			//						if (node.Children[i].Count == 0)
			//							node.Children[i] = node.Children[node.Children.Length - skipped++ - 1];
			//						else
			//							i++;
			//					}
			//					Node[] newArray = new Node[node.Children.Length - skipped];
			//					Array.Copy(node.Children, newArray, newArray.Length);
			//					node.Children = newArray;

			//					// convert this branch back into a leaf
			//					// Note: if count is zero, it will be chopped off
			//					if (node.Count < _load && node.Count > 0)
			//						ShrinkChild(node.Parent, node.Index);
			//				}
			//			}

			//			node.Count -= removals;
			//			return removals;
			//		}

			//		/// <summary>Removes all the items in a given space validated by a predicate.</summary>
			//		<#= documentation_AxisX_minX_AxisX_maxX #>
			//		/// <param name="where">The equality constraint of the removal.</param>
			//		public void RemoveEncapsulated(<#= chain_AxisX_minX_AxisX_maxX #>, Predicate<T> where)
			//		{
			//			this.RemoveEncapsulated(this._top, new Omnitree.Bounds<<#= chain_AxisX #>>(<#= chain_minX_maxX #>), where);
			//		}
			//		/// <summary>Removes all the items in a given space validated by a predicate.</summary>
			//		<#= documentation_AxisX_minX_AxisX_maxX #>
			//		/// <param name="where">The equality constraint of the removal.</param>
			//		public void RemoveEncapsulated(<#= chain_BoundAxisX_minX_BoundAxisX_maxX #>, Predicate<T> where)
			//		{
			//			this.RemoveEncapsulated(this._top, new Omnitree.Bounds<<#= chain_AxisX #>>(<#= chain_minX_maxX #>), where);
			//		}
			//		internal int RemoveEncapsulated(Node node, Omnitree.Bounds<<#= chain_AxisX #>> bounds, Predicate<T> where)
			//		{
			//			int removals = RemoveBase(node, bounds, where, (a, b) => this.EncapsulationCheck(a, b));
			//			Omnitree.ComputeLoads(_top.Count, ref _naturalLogLower, ref _naturalLogUpper, ref _load);
			//			return removals;
			//		}

			//		/// <summary>Removes all the items in a given space validated by a predicate.</summary>
			//		<#= documentation_AxisX_minX_AxisX_maxX #>
			//		/// <param name="where">The equality constraint of the removal.</param>
			//		public void RemoveOverlapped(<#= chain_AxisX_minX_AxisX_maxX #>, Predicate<T> where)
			//		{
			//			this.RemoveOverlapped(this._top, new Omnitree.Bounds<<#= chain_AxisX #>>(<#= chain_minX_maxX #>), where);
			//		}
			//		/// <summary>Removes all the items in a given space validated by a predicate.</summary>
			//		<#= documentation_AxisX_minX_AxisX_maxX #>
			//		/// <param name="where">The equality constraint of the removal.</param>
			//		public void RemoveOverlapped(<#= chain_BoundAxisX_minX_BoundAxisX_maxX #>, Predicate<T> where)
			//		{
			//			this.RemoveOverlapped(this._top, new Omnitree.Bounds<<#= chain_AxisX #>>(<#= chain_minX_maxX #>), where);
			//		}
			//		internal int RemoveOverlapped(Node node, Omnitree.Bounds<<#= chain_AxisX #>> bounds, Predicate<T> where)
			//		{
			//			int removals = RemoveBase(node, bounds, where, (a, b) => this.InclusionCheck(a, b));
			//			Omnitree.ComputeLoads(_top.Count, ref _naturalLogLower, ref _naturalLogUpper, ref _load);
			//			return removals;
			//		}

			//		internal int RemoveBase(
			//			Node node,
			//			Omnitree.Bounds<<#= chain_AxisX #>> bounds,
			//			Predicate<T> where,
			//			Omnitree.SpatialCheck<Omnitree.Bounds<<#= chain_AxisX #>>, Omnitree.Bounds<<#= chain_AxisX #>>> spatialCheck)
			//		{
			//			if (!InclusionCheck(node.Bounds, bounds))
			//				return 0;
			//			int removals = 0;

			//			// items
			//			Node.ValueNode current = node.Head;
			//			Node.ValueNode previous = null;
			//			while (!(current is null))
			//			{
			//				if (spatialCheck(bounds, GetBoundings(current.Value)) && where(current.Value))
			//				{
			//					removals++;
			//					if (previous is null)
			//					{
			//						node.Head = current.Next;
			//						goto HeadRemoved;
			//					}
			//					else
			//						previous.Next = current.Next;
			//				}
			//				previous = current;
			//			HeadRemoved:
			//				current = current.Next;
			//			}

			//			// children
			//			if (!(node.Children is null))
			//			{
			//				int skipped = 0;
			//				for (int i = 0; i + skipped < node.Children.Length; )
			//				{
			//					removals += this.RemoveBase(node.Children[i], bounds, where, spatialCheck);
			//					if (node.Children[i].Count == 0)
			//						node.Children[i] = node.Children[node.Children.Length - skipped++ - 1];
			//					else
			//						i++;
			//				}
			//				Node[] newArray = new Node[node.Children.Length - skipped];
			//				Array.Copy(node.Children, newArray, newArray.Length);
			//				node.Children = newArray;

			//				if (node.Count < _load && node.Count != 0)
			//					ShrinkChild(node.Parent, node.Index);
			//			}

			//			node.Count -= removals;
			//			return removals;
			//		}

			//		/// <summary>Tries to remove a value.</summary>
			//		/// <param name="value">The value to remove.</param>
			//		/// <param name="exception">The exception that occurred if the remove failed.</param>
			//		/// <returns>True if successful or false if not.</returns>
			//		public bool TryRemove(T value, out Exception exception)
			//		{
			//			Remove(value);
			//			exception = null;
			//			return true;
			//		}

			//		/// <summary>Removes all instances of a given value.</summary>
			//		public void Remove(T removal) => Omnitree.Remove(this, removal);

			//		/// <summary>Removes all instances of a given value.</summary>
			//		public void Remove(T removal, Func<T, T, bool> equate) => Omnitree.Remove(this, removal, equate);

			//		/// <summary>Removes all the items in a given space.</summary>
			//		<#= documentation_axisX #>
			//		/// <returns>The number of items that were removed.</returns>
			//		public void RemoveOverlapped(Axis1 axis1
			//<# for (int j = 2; j <= i; j++) { #>
			//			, Axis<#= j #> axis<#= j #>
			//<# } #>
			//			)
			//		{
			//			this.RemoveOverlapped(axis1, axis1
			//<# for (int j = 2; j <= i; j++) { #>
			//				, axis<#= j #>, axis<#= j #>
			//<# } #>
			//				);
			//			Omnitree.ComputeLoads(_top.Count, ref _naturalLogLower, ref _naturalLogUpper, ref _load);
			//		}

			//		/// <summary>Removes all the items in a given space validated by a predicate.</summary>
			//		<#= documentation_axisX #>
			//		/// <param name="where">The equality constraint of the removal.</param>
			//		public void RemoveOverlapped(<#= chain_AxisX_axisX #>, Predicate<T> where)
			//		{
			//			this.RemoveOverlapped(axis1, axis1
			//<# for (int j = 2; j <= i; j++) { #>
			//				, axis<#= j #>, axis<#= j #>
			//<# } #>
			//				, where);
			//			Omnitree.ComputeLoads(_top.Count, ref _naturalLogLower, ref _naturalLogUpper, ref _load);
			//		}

			//#endregion

			//#region Stepper And IEnumerable

			//		/// <summary>Traverses every item in the tree and performs the delegate in them.</summary>
			//		/// <param name="step">The delegate to perform on every item in the tree.</param>
			//		public void Stepper(Action<T> step) =>
			//			this.Stepper(step, this._top);

			//		internal void Stepper(Action<T> step, Node node)
			//		{
			//			Node.ValueNode list = node.Head;
			//			while (!(list is null))
			//			{
			//				step(list.Value);
			//				list = list.Next;
			//			}
			//			if (!(node.Children is null))
			//				foreach (Node child in node.Children)
			//					this.Stepper(step, child);
			//		}

			//		/// <summary>Traverses every item in the tree and performs the delegate in them.</summary>
			//		/// <param name="step">The delegate to perform on every item in the tree.</param>
			//		public StepStatus Stepper(Func<T, StepStatus> step) =>
			//			Stepper(step, _top);

			//		internal StepStatus Stepper(Func<T, StepStatus> step, Node node)
			//		{
			//			StepStatus status = StepStatus.Continue;

			//			for (Node.ValueNode list = node.Head; !(list is null); list = list.Next)
			//				if ((status = step(list.Value)) != StepStatus.Continue)
			//					break;

			//			if (!(node.Children is null))
			//				foreach (Node child in node.Children)
			//					if ((status = Stepper(step, child)) != StepStatus.Continue)
			//						break;

			//			return status;
			//		}

			//		/// <summary>Performs and specialized traversal of the structure and performs a delegate on every node within the provided dimensions.</summary>
			//		/// <param name="step">The delegate to perform on all items in the tree within the given bounds.</param>
			//		<#= documentation_AxisX_minX_AxisX_maxX #>
			//		public void StepperEncapsulated(Action<T> step, <#= chain_AxisX_minX_AxisX_maxX #>) =>
			//			StepperEncapsulated(step, _top, new Omnitree.Bounds<<#= chain_AxisX #>>(<#= chain_minX_maxX #>));

			//		/// <summary>Performs and specialized traversal of the structure and performs a delegate on every node within the provided dimensions.</summary>
			//		/// <param name="step">The delegate to perform on all items in the tree within the given bounds.</param>
			//		<#= documentation_AxisX_minX_AxisX_maxX #>
			//		public void StepperEncapsulated(Action<T> step, <#= chain_BoundAxisX_minX_BoundAxisX_maxX #>) =>
			//			StepperEncapsulated(step, _top, new Omnitree.Bounds<<#= chain_AxisX #>>(<#= chain_minX_maxX #>));

			//		internal void StepperEncapsulated(Action<T> step, Node node, Omnitree.Bounds<<#= chain_AxisX #>> bounds) =>
			//			StepperBase(step, node, bounds, (a, b) => this.EncapsulationCheck(a, b));

			//		/// <summary>Performs and specialized traversal of the structure and performs a delegate on every node within the provided dimensions.</summary>
			//		/// <param name="step">The delegate to perform on all items in the tree within the given bounds.</param>
			//		<#= documentation_AxisX_minX_AxisX_maxX #>
			//		public void StepperOverlapped(Action<T> step, <#= chain_AxisX_minX_AxisX_maxX #>) =>
			//			StepperOverlapped(step, _top, new Omnitree.Bounds<<#= chain_AxisX #>>(<#= chain_minX_maxX #>));

			//		/// <summary>Performs and specialized traversal of the structure and performs a delegate on every node within the provided dimensions.</summary>
			//		/// <param name="step">The delegate to perform on all items in the tree within the given bounds.</param>
			//		<#= documentation_AxisX_minX_AxisX_maxX #>
			//		public void StepperOverlapped(Action<T> step, <#= chain_BoundAxisX_minX_BoundAxisX_maxX #>) =>
			//			StepperOverlapped(step, _top, new Omnitree.Bounds<<#= chain_AxisX #>>(<#= chain_minX_maxX #>));

			//		internal void StepperOverlapped(Action<T> step, Node node, Omnitree.Bounds<<#= chain_AxisX #>> bounds) =>
			//			StepperBase(step, node, bounds, (a, b) => this.InclusionCheck(a, b));

			//		internal void StepperBase(
			//			Action<T> step,
			//			Node node,
			//			Omnitree.Bounds<<#= chain_AxisX #>> bounds,
			//			Omnitree.SpatialCheck<Omnitree.Bounds<<#= chain_AxisX #>>, Omnitree.Bounds<<#= chain_AxisX #>>> spatialCheck)
			//		{
			//			for (Node.ValueNode list = node.Head; !(list is null); list = list.Next)
			//				if (spatialCheck(bounds, GetBoundings(list.Value)))
			//					step(list.Value);

			//			if (!(node.Children is null))
			//			{
			//				foreach (Node child in node.Children)
			//					// optimization: stop bounds checking if space encapsulates node
			//					if (EncapsulationCheck(bounds, child.Bounds))
			//						this.Stepper(step, child);
			//					else if (InclusionCheck(child.Bounds, bounds))
			//						this.StepperBase(step, child, bounds, spatialCheck);
			//			}
			//		}

			//		/// <summary>Performs and specialized traversal of the structure and performs a delegate on every node within the provided dimensions.</summary>
			//		/// <param name="step">The delegate to perform on all items in the tree within the given bounds.</param>
			//		<#= documentation_AxisX_minX_AxisX_maxX #>
			//		public StepStatus StepperEncapsulated(Func<T, StepStatus> step, <#= chain_AxisX_minX_AxisX_maxX #>) =>
			//			StepperEncapsulated(step, _top, new Omnitree.Bounds<<#= chain_AxisX #>>(<#= chain_minX_maxX #>));

			//		/// <summary>Performs and specialized traversal of the structure and performs a delegate on every node within the provided dimensions.</summary>
			//		/// <param name="step">The delegate to perform on all items in the tree within the given bounds.</param>
			//		<#= documentation_AxisX_minX_AxisX_maxX #>
			//		public StepStatus StepperEncapsulated(Func<T, StepStatus> step, <#= chain_BoundAxisX_minX_BoundAxisX_maxX #>) =>
			//			StepperEncapsulated(step, _top, new Omnitree.Bounds<<#= chain_AxisX #>>(<#= chain_minX_maxX #>));

			//		internal StepStatus StepperEncapsulated(Func<T, StepStatus> step, Node node, Omnitree.Bounds<<#= chain_AxisX #>> bounds) =>
			//			StepperBase(step, node, bounds, (a, b) => this.EncapsulationCheck(a, b));

			//		/// <summary>Performs and specialized traversal of the structure and performs a delegate on every node within the provided dimensions.</summary>
			//		/// <param name="step">The delegate to perform on all items in the tree within the given bounds.</param>
			//		<#= documentation_AxisX_minX_AxisX_maxX #>
			//		public StepStatus StepperOverlapped(Func<T, StepStatus> step, <#= chain_AxisX_minX_AxisX_maxX #>) =>
			//			StepperOverlapped(step, _top, new Omnitree.Bounds<<#= chain_AxisX #>>(<#= chain_minX_maxX #>));

			//		/// <summary>Performs and specialized traversal of the structure and performs a delegate on every node within the provided dimensions.</summary>
			//		/// <param name="step">The delegate to perform on all items in the tree within the given bounds.</param>
			//		<#= documentation_AxisX_minX_AxisX_maxX #>
			//		public StepStatus StepperOverlapped(Func<T, StepStatus> step, <#= chain_BoundAxisX_minX_BoundAxisX_maxX #>) =>
			//			StepperOverlapped(step, _top, new Omnitree.Bounds<<#= chain_AxisX #>>(<#= chain_minX_maxX #>));

			//		internal StepStatus StepperOverlapped(Func<T, StepStatus> step, Node node, Omnitree.Bounds<<#= chain_AxisX #>> bounds) =>
			//			StepperBase(step, node, bounds, (a, b) => this.InclusionCheck(a, b));

			//		internal StepStatus StepperBase(
			//			Func<T, StepStatus> step,
			//			Node node,
			//			Omnitree.Bounds<<#= chain_AxisX #>> bounds,
			//			Omnitree.SpatialCheck<Omnitree.Bounds<<#= chain_AxisX #>>, Omnitree.Bounds<<#= chain_AxisX #>>> spatialCheck)
			//		{
			//			StepStatus status = StepStatus.Continue;

			//			for (Node.ValueNode list = node.Head; !(list is null); list = list.Next)
			//				if (spatialCheck(bounds, GetBoundings(list.Value)) &&
			//					(status = step(list.Value)) != StepStatus.Continue)
			//					break;

			//			if (!(node.Children is null))
			//			{
			//				foreach (Node child in node.Children)
			//					// optimization: stop bounds checking if space encapsulates node
			//					if (EncapsulationCheck(bounds, child.Bounds) &&
			//						(status = this.Stepper(step, child)) != StepStatus.Continue)
			//						break;
			//					else if (!InclusionCheck(child.Bounds, bounds) &&
			//						(status = this.StepperBase(step, child, bounds, spatialCheck)) != StepStatus.Continue)
			//						break;
			//			}

			//			return status;
			//		}

			//		/// <summary>Performs and specialized traversal of the structure and performs a delegate on every node within the provided dimensions.</summary>
			//		/// <param name="step">The delegate to perform on all items in the tree within the given bounds.</param>
			//		<#= documentation_axisX #>
			//		public void StepperOverlapped(Action<T> step, <#= chain_AxisX_axisX #>) =>
			//			StepperOverlapped(step, this._top, new Omnitree.Bounds<<#= chain_AxisX #>>(axis1, axis1
			//<# for (int j = 2; j <= i; j++) { #>
			//				, axis<#= j #>, axis<#= j #>
			//<# } #>
			//			));

			//		/// <summary>Performs and specialized traversal of the structure and performs a delegate on every node within the provided dimensions.</summary>
			//		/// <param name="step">The delegate to perform on all items in the tree within the given bounds.</param>
			//		<#= documentation_axisX #>
			//		public StepStatus StepperOverlapped(Func<T, StepStatus> step, <#= chain_AxisX_axisX #>) =>
			//			StepperOverlapped(step, this._top, new Omnitree.Bounds<<#= chain_AxisX #>>(axis1, axis1
			//<# for (int j = 2; j <= i; j++) { #>
			//				, axis<#= j #>, axis<#= j #>
			//<# } #>
			//				));

			//		System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() => GetEnumerator();

			//		public System.Collections.Generic.IEnumerator<T> GetEnumerator()
			//		{
			//			// Note: this can be optimized.
			//			IList<T> list = new ListLinked<T>();
			//			Stepper(x => list.Add(x));
			//			return list.GetEnumerator();
			//		}

			//#endregion

			//#region Helpers

			//		internal bool StraddlesLines(Omnitree.Bounds<<#= chain_AxisX #>> bounds, Omnitree.Vector<<#= chain_AxisX #>> vector) =>
			//			Omnitree.StraddlesLines(bounds, vector
			//<# for (int j = 1; j <= i; j++) { #>
			//				, _compare<#= j #>
			//<# } #>
			//				);

			//		/// <summary>Computes the child index that contains the desired dimensions.</summary>
			//		/// <param name="pointOfDivision">The point of division to compare against.</param>
			//		/// <param name="bounds">The dimensions to determine the child index.</param>
			//		/// <returns>The computed child index based on the coordinates relative to the center of the node.</returns>
			//		internal <#= child_index_type #> DetermineChildIndex(Omnitree.Vector<<#= chain_AxisX #>> pointOfDivision, Omnitree.Bounds<<#= chain_AxisX #>> bounds)
			//		{
			//			// make sure a child encapsulates the bounds (otherwise the bounds cannot move down the tree)
			//			if (StraddlesLines(bounds, pointOfDivision))
			//				return -1;

			//			<#= child_index_type #> child = 0;
			//<# for (int j = 1; j <= i; j++) { #>
			//			if (!bounds.Min<#= j #>.Exists || !(this._compare<#= j #>(bounds.Min<#= j #>.Value, pointOfDivision.Axis<#= j #>) == CompareResult.Less))
			//				child += 1 << <#= j - 1 #>;
			//<# } #>
			//			return child;
			//		}

			//		/// <summary>Converts a branch back into a leaf when the count is reduced.</summary>
			//		/// <param name="parent">The parent to shrink a child of.</param>
			//		/// <param name="child_index">The index of the child to shrink.</param>
			//		internal void ShrinkChild(Node parent, <#= child_index_type #> child_index)
			//		{
			//			Node leaf;
			//			Node removal = null;
			//			if (parent is null) // top of tree
			//			{
			//				removal = this._top;
			//				leaf = new Node(Omnitree.Bounds<<#= chain_AxisX #>>.None, null, -1);
			//				this._top = leaf;
			//			}
			//			else // non-top branch
			//			{
			//				removal = parent[child_index];
			//				leaf = new Node(removal.Bounds, removal.Parent, removal.Index);
			//				parent[child_index] = leaf;
			//			}

			//			this.Stepper((T step) => { leaf.Add(step); }, removal);
			//		}

			//		/// <summary>Reduces the counts of all the parents of a given node by a given amount.</summary>
			//		/// <param name="parent">The starting parent of the reduction.</param>
			//		/// <param name="reduction">The amount to reduce the parent counts by.</param>
			//		internal void ReduceParentCounts(Node parent, int reduction)
			//		{
			//			IncreaseParentCounts(parent, -reduction);
			//		}

			//		/// <summary>Increases the counts of all the parents of a given node by a given amount.</summary>
			//		/// <param name="parent">The starting parent of the increase.</param>
			//		/// <param name="increase">The amount to increase the parent counts by.</param>
			//		internal void IncreaseParentCounts(Node parent, int increase)
			//		{
			//			Node node = parent;
			//			while (!(node is null))
			//			{
			//				node.Count += increase;
			//				node = node.Parent;
			//			}
			//		}

			//		/// <summary>Checks a node for inclusion (overlap) between two bounds.</summary>
			//		/// <returns>True if the spaces overlap; False if not.</returns>
			//		internal bool InclusionCheck(Omnitree.Bounds<<#= chain_AxisX #>> a, Omnitree.Bounds<<#= chain_AxisX #>> b) =>
			//			Omnitree.InclusionCheck(a, b
			//<# for (int j = 1; j <= i; j++) { #>
			//			, _compare<#= j #>
			//<# } #>
			//			);

			//		/// <summary>Checks if a space encapsulates a point.</summary>
			//		/// <returns>True if the space encapsulates the point; False if not.</returns>
			//		internal bool EncapsulationCheck(Omnitree.Bounds<<#= chain_AxisX #>> bounds, Omnitree.Vector<<#= chain_AxisX #>> vector) =>
			//			Omnitree.EncapsulationCheck(bounds, vector
			//<# for (int j = 1; j <= i; j++) { #>
			//			, _compare<#= j #>
			//<# } #>
			//			);

			//		/// <summary>Checks if a space (left) encapsulates another space (right).</summary>
			//		/// <returns>True if the left space encapsulates the right; False if not.</returns>
			//		internal bool EncapsulationCheck(Omnitree.Bounds<<#= chain_AxisX #>> a, Omnitree.Bounds<<#= chain_AxisX #>> b) =>
			//			Omnitree.EncapsulationCheck(a, b
			//<# for (int j = 1; j <= i; j++) { #>
			//			, _compare<#= j #>
			//<# } #>
			//			);

			//		/// <summary>Checks for equality between two locations.</summary>
			//		/// <returns>True if equal; False if not;</returns>
			//		internal bool EqualsCheck(Omnitree.Vector<<#= chain_AxisX #>> a, Omnitree.Vector<<#= chain_AxisX #>> b) =>
			//			Omnitree.EqualsCheck(a, b
			//<# for (int j = 1; j <= i; j++) { #>
			//			, Equate.FromCompare(_compare<#= j #>)
			//<# } #>
			//			);

			//		/// <summary>Gets the nearest parent that encapsulates a location.</summary>
			//		/// <param name="node">The starting node to find the encapsulating parent of the location.</param>
			//		/// <param name="bounds">The bounds to get the encapsulating parent from.</param>
			//		/// <returns>The nearest node that encapsulates the given location.</returns>
			//		internal Node GetEncapsulationParent(Node node, Omnitree.Bounds<<#= chain_AxisX #>> bounds)
			//		{
			//			while (!(node is null) && !EncapsulationCheck(node.Bounds, bounds))
			//			{
			//				node = node.Parent;
			//			}
			//			return node;
			//		}

			//		internal Omnitree.Bounds<<#= chain_AxisX #>> GetBoundings(T value)
			//		{
			//<# for (int j = 1; j <= i; j++) { #>
			//			Omnitree.Bound<Axis<#= j #>> min<#= j #>; Omnitree.Bound<Axis<#= j #>> max<#= j #>;
			//<# } #>
			//			this._getBounds(value,
			//				out min1, out max1
			//<# for (int j = 2; j <= i; j++) { #>,
			//				out min<#= j #>, out max<#= j #>
			//<# } #>
			//				);
			//			return new Omnitree.Bounds<<#= chain_AxisX #>>(
			//				min1, max1
			//<# for (int j = 2; j <= i; j++) { #>,
			//				min<#= j #>, max<#= j #>
			//<# } #>
			//				);
			//		}

			//#endregion

			//#endregion
			//	}

			//#endregion
			//<# } #>

			//#endregion
			//}



			//File.WriteAllText("../../../temp.cs", file.ToString());
		}
	}
}
